[
  {
    "path": ".cirrus.yml",
    "content": "env:\n  CIRRUS_CLONE_DEPTH: 1\n\nlinux_x64_task:\n  container:\n    cpu: 2\n    memory: 2G\n    image: gcc:15.2.0\n\n  install_script:\n    - apt-get update -qq\n    - apt-get install -qq liblzo2-dev libssl-dev libc6-dev cmake\n\n  build_script:\n    - ./build.sh\n\ndarwin_aarch64_task:\n  macos_instance:\n    image: ghcr.io/cirruslabs/macos-ventura-base:latest\n\n  install_script:\n    - brew install openssl@3 lzo\n    - brew reinstall openssl@3\n\n  build_script:\n    - ./build.sh\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".gitattributes",
    "content": "# auto-detect text files; use LF\n* text=auto eol=lf\n\n# text extensions\n*.txt text\n*.md text\n*.c text\n*.h text\n*.cpp text\n*.yml text\n*.cmake text\n\n# important that these use LF\n*.sh text eol=lf\n*.py text eol=lf\n\n# specific text filenames\n.gitattributes text\n.gitignore text\n.editorconfig text\nAUTHORS text\nCOPYING text\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: SonarQube\non:\n  push:\n    branches:\n      - master\n      - develop\n  pull_request:\n    types: [opened, synchronize, reopened]\njobs:\n  build:\n    name: Build and analyze\n    runs-on: ubuntu-latest\n    env:\n      BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0  # Shallow clones should be disabled for a better relevancy of analysis\n      - name: Install Dependencies\n        run: |\n          sudo apt-get install -y git build-essential cmake liblzo2-dev libssl-dev libc6-dev\n      - name: Install Build Wrapper\n        uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5\n      - name: Run Build Wrapper\n        run: |\n          build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} ./build.sh\n      - name: SonarQube Scan\n        uses: SonarSource/sonarqube-scan-action@v5\n        env:\n          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}\n        with:\n          args: >\n            --define sonar.cfamily.compile-commands=\"${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json\"\n\n"
  },
  {
    "path": ".gitignore",
    "content": "### CMake ###\nCMakeCache.txt\nCMakeFiles\nMakefile\ncmake_install.cmake\ninstall_manifest.txt\n\n### C ###\n# Object files\n*.o\n\n# Libraries\n*.a\n*.la\n\n# Executables\n*.exe\n*.out\n\n\n### Epk2Extract ###\n\n# build\nbuild_linux\nbuild_cygwin\nbuild_osx\n\n# Linux build artifacts\nsrc/epk2extract\nsrc/tools/idb_extract\nsrc/tools/jffs2extract\nsrc/tools/lzhs_scanner\nsrc/tools/lzhsenc\n"
  },
  {
    "path": ".sonarcloud_gen.sh",
    "content": "#!/bin/sh\ncsv_prop(){\n\techo -ne \"$1=\"\n\tcat | paste -sd,\n}\n\ngen(){\n\tcat <<-EOF\n\t## THIS FILE IS AUTOGENERATED\n\t## edit .sonarcloud_gen.sh instead\n\tsonar.projectKey=openlgtv_epk2extract\n\tsonar.organization=openlgtv\n\n\tEOF\n\n\t(cat <<-EOF\n\tr1\n\tEOF\n\t) | csv_prop \"sonar.issue.ignore.multicriteria\"\n\n\techo \"\"\n\n\tcat <<-EOF\n\t# format string is not a string literal\n\tsonar.issue.ignore.multicriteria.r1.ruleKey=c:S5281\n\tsonar.issue.ignore.multicriteria.r1.resourceKey=**\n\tEOF\n\n\techo \"\"\n\n\t(cat <<-EOF\n\tsrc/*.c\n\tsrc/lzhs/*.c\n\tsrc/stream/*.c\n\tsrc/tools/*.c\n\tinclude/*.h\n\tinclude/lzhs/*.h\n\tinclude/realtek/*.h\n\tinclude/stream/*.h\n\tEOF\n\t) | csv_prop \"sonar.inclusions\"\n\n}\n\ncd \"$(dirname \"$(readlink -f \"$0\")\")\"\ngen > sonar-project.properties\n"
  },
  {
    "path": "AUTHORS",
    "content": "This project is covered by the GPL licence. See COPYING for details.\n\nepk2extract contributors list:\n- Arno1\n- cronix\n- jenya\n- lprot\n- rtokarev (sym handling)\n- Smx (smxdev4@gmail.com, current maintainer)\n- sirius (original author of epk2extract)\n- tbage\n- xeros\n\nSpecial thanks to:\n- All the testers\n- Authors of the original compression algorithms and libraries\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "set(CMAKE_LEGACY_CYGWIN_WIN32 0)\n\ncmake_minimum_required(VERSION 3.13)\nproject(epk2extract)\n\nif( NOT CMAKE_BUILD_TYPE )\n\tset(CMAKE_BUILD_TYPE Debug)\nendif()\n\nset(CMAKE_CXX_FLAGS_TEST \"-Ofast\")\nset(CMAKE_C_FLAGS_TEST \"-Ofast -funroll-loops -fprefetch-loop-arrays -march=native\")\n\nset(CMAKE_C_STANDARD 99)\nset(CMAKE_CXX_STANDARD 11)\n\nset(CMAKE_MODULE_PATH \"${PROJECT_SOURCE_DIR}/cmake-modules/\")\nfind_package(OpenSSL REQUIRED)\nfind_package(LZO REQUIRED)\nfind_package(Threads REQUIRED)\nfind_package(ZLIB REQUIRED)\nfind_library(M_LIB m REQUIRED)\n\nadd_subdirectory(src)\n"
  },
  {
    "path": "COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (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    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n"
  },
  {
    "path": "README.md",
    "content": "[![Build Status](https://travis-ci.org/openlgtv/epk2extract.svg?branch=master)](https://travis-ci.org/openlgtv/epk2extract)\n\nepk2extract\n===========\n\n[![Join the chat at https://gitter.im/openlgtv/epk2extract](https://badges.gitter.im/openlgtv/epk2extract.svg)](https://gitter.im/openlgtv/epk2extract?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\nJoin on Discord: https://discord.gg/xWqRVEm\n\nepk2extract is a tool that can extract, decrypt, convert multiple file formats that can be found in LG TV sets and similar devices.\n\nSupported Formats:\n===========================================\n**NOTE: To unpack epk v2 and v3 you need proper AES and RSA keys for decryption. To get them you will need to dump them from a running TV.**\n\n**NOTE: To decrypt PVR recordings you need a dump of the unique AES-128 key from your TV**\n\n| Format\t| Notes\n| :-----\t| :-----\n| epk v1\t| First version of epk format, not encrypted and not signed\n| epk v2\t| Introduces signing and encryption, keys needed\n| epk v3   \t| Introduced with WebOS. Keys needed\n| Mediatek pkg | UPG/PKG files used by Hisense/Sharp/Philips (missing Philips AES key) and possibly others\n| Philips \"fusion\" | Upgrade files used by some Philips TVs\n| squashfs\t|\n| cramfs\t|\n| lz4\t\t| Slightly modified version with header magic\n| lzo\t\t|\n| gzip\t\t|\n| jffs2\t\t|\n| lzhs\t\t| Special compression for MTK bootloaders (boot.pak, tzfw.pak), uses lzss + huffman\n| lzhs_fs   | LZHS compressed filesystem used in MTK Upgrade files for the external writable partition (3rdw)\n| mtdinfo/partinfo |  LG Partition table format (mtdi.pak, part.pak)\n| str/pif\t| PVR recording format that can be found in netcast models\n| sym\t\t| LG Debugging symbols. Can extract function names and addresses to an IDA script file (idc)\n\nAlthough epk2extract is only tested on LG firmware files, you may use it to extract other files like a general unpack tool, as long as they are supported according to the table above.\n\n**!!WARNING!!**<br>\n**epk2extract isn't designed to repack files**<br>\n**If you wish to repack modified files, follow the openlgtv wiki/forum, and do it in a Linux environment (no cygwin)**<br>\n**Don't repack files extracted in cygwin environment**<br>\n**In any case, you do so at your own risk**<br>\n\n*THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE*\n\n| Tools:\t| Description\n| :----\t\t| :----\n| lzhsenc\t| Compresses a given file with lzhs algorithm\n| lzhs_scanner\t| Scans a given file to find lzhs files, and extracts them\n| idb_extract | Extracts Image Database (IDB) files that can be found in LG firmwares\n| jffs2extract | Extracts JFFS2 images. Supports various compression algorithms\n\n\nTo compile on Linux:\n===========================================\n\n### Install build dependencies:\nUbuntu/Debian:\n```shell\napt-get install git build-essential cmake liblzo2-dev libssl-dev libc6-dev zlib1g-dev\n```\nMandriva/Mageia:\n```shell\nurpmi git task-c++-devel cmake liblzo-devel libopenssl-devel glibc-devel --auto\n```\n\n### Build it\n```shell\n./build.sh\n```\n\nAfter building, epk2extract can be found in ./build_\\<platform\\>/\n\n\nTo compile on Cygwin:\n=====================\n\n### Install Cygwin and during setup select following packages:\n\n    Devel -> gcc-g++, git, cmake, make\n    Libs  -> liblzo2-devel, zlib-devel\n    Net   -> openssl-devel\n    Utils -> ncurses\n\n### Build it\n```shell\n./build.sh\n```\n\nThe build script automatically copies required shared libraries to the ./build_cygwin/ folder, so you can use epk2extract standalone/portable without a full cygwin installation.\n\n\n=====================\n### How to speed up extraction process\nYou can build the test build, which contains compiler optimizations, with this command\n```shell\nCMAKE_FLAGS=-DCMAKE_BUILD_TYPE=Test ./build.sh\n```\nThe Test build is orders of magnitude faster than the Debug build\n\n### To use:\n\nPut *.pem and AES.key files in the same directory as the epk2extract binary.\n\nRun it via sudo/fakeroot to avoid warnings (while extracting device nodes from rootfs):\n\n    fakeroot ./epk2extract file\n\n## To get IDC from SYM run:\n\n    ./epk2extract xxxxxxxx.sym\n\n## To decode part.pak or mtdi.pak do:\n\n    ./epk2extract part.pak\n\nOr use partinfo.py (**deprected**)\n\n    python partinfo.py part.pak\n"
  },
  {
    "path": "build.sh",
    "content": "#!/bin/bash\n#epk2extract build script\n#Copyright 2016 Smx <smxdev4@gmail.com>\n#All right reserved\n\nnormal='tput sgr0'\nlred='printf \\033[01;31m'\nlgreen='printf \\033[01;32m'\nlyellow='printf \\033[01;33m'\nlblue='printf \\033[01;34m'\nwhite='printf \\033[01;37m'\n\ncwd=$(pwd)\nsrcdir=`cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd`\n\nexe=(\n\t\"epk2extract\" \"tools/lzhsenc\"\n\t\"tools/lzhs_scanner\" \"tools/idb_extract\"\n\t\"tools/jffs2extract\" \"tools/tsfile\"\n)\n\nnproc_cmd=\"nproc\"\n\nif [ \"$OSTYPE\" == \"cygwin\" ]; then rel=build_cygwin\nelif [[ \"$OSTYPE\" =~ \"linux\" ]]; then rel=build_linux\nelif [[ \"$OSTYPE\" =~ \"darwin\" ]]; then\n\tnproc_cmd=\"sysctl -n hw.logicalcpu\"\n\trel=build_osx\n\tCMAKE_FLAGS=\"-DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl ${CMAKE_FLAGS}\"\nelse\n\t$lred; \"Can't build - unknown OS type. Aborting...\"; $normal\n\texit 1\nfi\n\ninstalldir=$srcdir/$rel\nobjdir=$installdir/obj\n\ncd $srcdir\n\nif [ \"$1\" == \"clean\" ]; then\n\t$lyellow; echo \"Removing cmake cache and make files\"; $normal\n\trm -r $objdir\n\tif [ -d \"$installdir\" ]; then\n\t\t$lyellow; echo \"Removing build dir\"; $normal\n\t\trm -r \"$installdir\"\n\tfi\n\t$lgreen; echo \"Done!\"; $normal\n\texit 0\nfi\n\n$lyellow; echo \"Building epk2extract\"; $normal\nif [ ! -e \"$rel/obj\" ]; then\n\tmkdir -p $objdir\nfi\n\ncd $objdir\n\nNUM_THREADS=$($nproc_cmd)\n\ncase \"$1\" in\n\t\"-v\")\n\t\tMAKE_FLAGS=\"${MAKE_ARGS} VERBOSE=1 -j${NUM_THREADS}\"\n\t\t;;\nesac\n\ncmake $srcdir $CMAKE_FLAGS\nmake $MAKE_FLAGS\nRESULT=$?\ncd src\n\nif [ ! $RESULT -eq 0 ]; then\n\t$lred; echo \"Build Failed!\"; $normal\n\texit 1\nfi\n\nif [ \"$rel\" == \"build_cygwin\" ]; then\n\tfor exe in ${exe[@]}; do\n\t\tcp $exe.exe $installdir/\n\tdone\n\tif [ \"$HOSTTYPE\" == \"i686\" ]; then #cygwin32\n\t\tsharedlibs=(\"cygz.dll\" \"cygwin1.dll\" \"cyglzo2-2.dll\" \"cyggcc_s-1.dll\" \"cygcrypto-1.1.dll\" \"cygstdc++-6.dll\")\n\telif [ \"$HOSTTYPE\" == \"x86_64\" ]; then #cygwin64\n\t\tsharedlibs=(\"cygz.dll\" \"cygwin1.dll\" \"cyglzo2-2.dll\" \"cygcrypto-1.1.dll\" \"cyggcc_s-seh-1.dll\" \"cygstdc++-6.dll\")\n\tfi\n\tfor cyglib in ${sharedlibs[@]}; do\n\t\t$white; echo \"Installing $cyglib\"; $normal\n\t\tislibok=$(which \"$cyglib\" &>/dev/null; echo $?)\n\t\tif [ $islibok == 0 ]; then\n\t\t\tcp `which $cyglib` $installdir/\n\t\telse\n\t\t\t$lred\n\t\t\techo \"Something wrong! $cyglib not found.\"\n\t\t\techo \"Verify your cygwin installation and try again.\"\n\t\t\t$normal\n\t\t\texit 1\n\t\tfi\n\tdone\nelse\n\tfor exe in ${exe[@]}; do\n\t\tcp $exe $installdir/\n\tdone\nfi\n\nif [ -d \"$srcdir/keys\" ]; then\n\tfor key in $(find ${srcdir}/keys -iname \"*.pem\" -or -iname \"*.key\" | sort); do\n\t\t$lblue; echo \"Installing $(basename $key)\"; $normal\n\t\tcp $key $installdir/\n\tdone\nfi\n$lgreen; echo \"Build completed!\"; $normal\nexit 0\n"
  },
  {
    "path": "cmake-modules/FindLZO.cmake",
    "content": "# Find liblzo2\n# LZO_FOUND - system has the LZO library\n# LZO_INCLUDE_DIR - the LZO include directory\n# LZO_LIBRARIES - The libraries needed to use LZO\n\nif (LZO_INCLUDE_DIR AND LZO_LIBRARIES)\n\t# in cache already\n\tSET(LZO_FOUND TRUE)\nelse (LZO_INCLUDE_DIR AND LZO_LIBRARIES)\n\tFIND_PATH(LZO_INCLUDE_DIR lzo/lzo1x.h\n\t\t ${LZO_ROOT}/include/\n\t\t /usr/include/\n\t\t /usr/local/include/\n\t\t /sw/lib/\n\t\t /sw/local/lib/\n\t)\n\n\tif(WIN32 AND MSVC)\n\telse(WIN32 AND MSVC)\n\t\tFIND_LIBRARY(LZO_LIBRARIES NAMES lzo2\n\t\t\tPATHS\n\t\t\t${LZO_ROOT}/lib\n\t\t\t/usr/lib\n\t\t\t/usr/local/lib\n\t\t\t/sw/lib\n\t\t\t/sw/local/lib\n\t\t)\n\tendif(WIN32 AND MSVC)\n\n\tif (LZO_INCLUDE_DIR AND LZO_LIBRARIES)\n\t\t set(LZO_FOUND TRUE)\n\tendif (LZO_INCLUDE_DIR AND LZO_LIBRARIES)\n\n\tif (LZO_FOUND)\n\t\t if (NOT LZO_FIND_QUIETLY)\n\t\t\t\tmessage(STATUS \"Found LZO: ${LZO_LIBRARIES}\")\n\t\t endif (NOT LZO_FIND_QUIETLY)\n\telse (LZO_FOUND)\n\t\t if (LZO_FIND_REQUIRED)\n\t\t\t\tmessage(FATAL_ERROR \"Could NOT find LZO\")\n\t\t endif (LZO_FIND_REQUIRED)\n\tendif (LZO_FOUND)\n\n\tMARK_AS_ADVANCED(LZO_INCLUDE_DIR LZO_LIBRARIES)\nendif (LZO_INCLUDE_DIR AND LZO_LIBRARIES)\n"
  },
  {
    "path": "code_format.sh",
    "content": "#!/bin/bash\nfunction my_indent() {\n\tfile=\"$1\"\n\tindent \\\n\t\t--linux-style \\\n\t\t--use-tabs \\\n\t\t--tab-size4 \\\n\t\t--indent-level4 \\\n\t\t--preprocessor-indentation4 \\\n\t\t--else-endif-column0 \\\n\t\t--braces-on-if-line \\\n\t\t--braces-on-func-def-line \\\n\t\t--braces-on-struct-decl-line \\\n\t\t--line-length0 \\\n\t\t\t\"$file\"\n}\n\nif [ -z \"$1\" ]; then\n\tdirs=\"src include\"\nelif [ -d \"$1\" ]; then\n\tdirs=\"$1\"\nelif [ -f \"$1\" ]; then\n\techo \"Reindenting ${1}...\"\n\tmy_indent \"$1\"\n\texit 0\nfi\n\nfor file in `find src include -type f -name \"*.c\" -or -name \"*.cpp\" -or -name \"*.h\"`; do\n\techo \"Reindenting ${file}...\"\n\tmy_indent \"$file\"\ndone\nexit 0\n"
  },
  {
    "path": "include/common.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#ifndef __COMMON_H\n#define __COMMON_H\n\n/* Branch Prediction Hints */\n#ifdef __GNUC__\n#define LIKELY(x)    __builtin_expect (!!(x), 1)\n#define UNLIKELY(x)  __builtin_expect (!!(x), 0)\n#else\n#define LIKELY(x)\t(x)\n#define UNLIKELY(x)\t(x)\n#endif\n\n#ifdef __GNUC__\n#define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))\n#else\n#define UNUSED(x) UNUSED_ ## x\n#endif\n\n#ifdef __GNUC__\n#define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x\n#else\n#define UNUSED_FUNCTION(x) UNUSED_ ## x\n#endif\n\n#ifdef __GNUC__\n#define FORMAT_PRINTF(x, y) __attribute__((__format__(__printf__, (x), (y))))\n#else\n#define FORMAT_PRINTF(x, y)\n#endif\n\n#define countof(x) (sizeof(x) / sizeof((x)[0]))\n\n#endif\n"
  },
  {
    "path": "include/config.h",
    "content": "/**\n * Copyright 20xx sirius\n * All right reserved\n */\n#ifndef CONFIG_H_\n#    define CONFIG_H_\n\n#include <stdbool.h>\n\ntypedef struct {\n\tchar *config_dir;\n\tchar *dest_dir;\n\tint enableSignatureChecking;\n\tbool noAutoUnsquashfs;\n\tbool signatureOnly;\n} config_opts_t;\n\nextern config_opts_t config_opts;\n\n#    define G_DIR_SEPARATOR_S \"/\"\n\n#    if defined(__APPLE__)\n#        include <sys/syslimits.h>\n#    elif defined(__CYGWIN__)\n#        include <limits.h>\n#    else\n#        include <linux/limits.h>\n#    endif\n\n#    ifndef PATH_MAX\n#        define PATH_MAX        4096\t/* # chars in a path name including nul */\n#    endif\n\n#endif /* CONFIG_H_ */\n"
  },
  {
    "path": "include/cramfs/cramfs.h",
    "content": "#ifndef __CRAMFS_H\n#define __CRAMFS_H\n\n#define CRAMFS_MAGIC\t\t0x28cd3d45\n\t\t\t\t\t\t\t\t\t\t/* some random number */\n#define CRAMFS_SIGNATURE\t\"Compressed ROMFS\"\n\n// Needed by cramfs\ntypedef unsigned char u8;\ntypedef unsigned short u16;\ntypedef unsigned int u32;\n\n/*\n * Reasonably terse representation of the inode data.\n */\nstruct cramfs_inode {\n\tu32 mode:16, uid:16;\n\t/* SIZE for device files is i_rdev */\n\tu32 size:24, gid:8;\n\t/* NAMELEN is the length of the file name, divided by 4 and\n\t   rounded up.  (cramfs doesn't support hard links.) */\n\t/* OFFSET: For symlinks and non-empty regular files, this\n\t   contains the offset (divided by 4) of the file data in\n\t   compressed form (starting with an array of block pointers;\n\t   see README).  For non-empty directories it is the offset\n\t   (divided by 4) of the inode of the first file in that\n\t   directory.  For anything else, offset is zero. */\n\tu32 namelen:6, offset:26;\n};\n\n/*\n * Superblock information at the beginning of the FS.\n */\nstruct cramfs_super {\n\tu32 magic;\t\t\t\t\t/* 0x28cd3d45 - random number */\n\tu32 size;\t\t\t\t\t/* Not used.  mkcramfs currently\n\t\t\t\t\t\t\t\t   writes a constant 1<<16 here. */\n\tu32 flags;\t\t\t\t\t/* 0 */\n\tu32 future;\t\t\t\t\t/* 0 */\n\tu8 signature[16];\t\t\t/* \"Compressed ROMFS\" */\n\tu8 fsid[16];\t\t\t\t/* random number */\n\tu8 name[16];\t\t\t\t/* user-defined name */\n\tstruct cramfs_inode root;\t/* Root inode data */\n};\n\n/*\n * Valid values in super.flags.  Currently we refuse to mount\n * if (flags & ~CRAMFS_SUPPORTED_FLAGS).  Maybe that should be\n * changed to test super.future instead.\n */\n#define CRAMFS_SUPPORTED_FLAGS (0xff)\n\n/* Uncompression interfaces to the underlying zlib */\nint cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen);\nint cramfs_uncompress_init(void);\nint cramfs_uncompress_exit(void);\n\nint is_cramfs_image(char const *imagefile, char *endian);\nint uncramfs(char const *dirname, char const *imagefile);\n\n#endif\n"
  },
  {
    "path": "include/cramfs/cramfs_fs.h",
    "content": "#ifndef __CRAMFS_FS_H\n#    define __CRAMFS_FS_H\n\n#    include <sys/types.h>\n\n#    define CRAMFS_MAGIC\t\t0x28cd3d45\n\t\t\t\t\t\t\t\t\t\t/* some random number */\n\n// Needed by cramfs\ntypedef unsigned char u8;\ntypedef unsigned short u16;\ntypedef unsigned int u32;\n\n/*\n * Width of various bitfields in struct cramfs_inode.\n * Primarily used to generate warnings in mkcramfs.\n */\n#    define CRAMFS_MODE_WIDTH 16\n#    define CRAMFS_UID_WIDTH 16\n#    define CRAMFS_SIZE_WIDTH 24\n#    define CRAMFS_GID_WIDTH 8\n#    define CRAMFS_NAMELEN_WIDTH 6\n#    define CRAMFS_OFFSET_WIDTH 26\n\n/*\n * Since inode.namelen is a unsigned 6-bit number, the maximum cramfs\n * path length is 63 << 2 = 252.\n */\n#    define CRAMFS_MAXPATHLEN (((1 << CRAMFS_NAMELEN_WIDTH) - 1) << 2)\n\n/*\n * Reasonably terse representation of the inode data.\n */\nstruct cramfs_inode {\n\tu32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH;\n\t/* SIZE for device files is i_rdev */\n\tu32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH;\n\t/* NAMELEN is the length of the file name, divided by 4 and\n\t   rounded up.  (cramfs doesn't support hard links.) */\n\t/* OFFSET: For symlinks and non-empty regular files, this\n\t   contains the offset (divided by 4) of the file data in\n\t   compressed form (starting with an array of block pointers;\n\t   see README).  For non-empty directories it is the offset\n\t   (divided by 4) of the inode of the first file in that\n\t   directory.  For anything else, offset is zero. */\n\tu32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH;\n};\n\nstruct cramfs_info {\n\tu32 crc;\n\tu32 edition;\n\tu32 blocks;\n\tu32 files;\n};\n\n/*\n * Superblock information at the beginning of the FS.\n */\nstruct cramfs_super {\n\tu32 magic;\t\t\t\t\t/* 0x28cd3d45 - random number */\n\tu32 size;\t\t\t\t\t/* length in bytes */\n\tu32 flags;\t\t\t\t\t/* feature flags */\n\tu32 future;\t\t\t\t\t/* reserved for future use */\n\tu8 signature[16];\t\t\t/* \"Compressed ROMFS\" */\n\tstruct cramfs_info fsid;\t/* unique filesystem info */\n\tu8 name[16];\t\t\t\t/* user-defined name */\n\tstruct cramfs_inode root;\t/* root inode data */\n};\n\n/*\n * Feature flags\n *\n * 0x00000000 - 0x000000ff: features that work for all past kernels\n * 0x00000100 - 0xffffffff: features that don't work for past kernels\n */\n#    define CRAMFS_FLAG_FSID_VERSION_2\t0x00000001\n\t\t\t\t\t\t\t\t\t\t\t\t/* fsid version #2 */\n#    define CRAMFS_FLAG_SORTED_DIRS\t\t0x00000002\n\t\t\t\t\t\t\t\t\t\t\t\t/* sorted dirs */\n#    define CRAMFS_FLAG_HOLES\t\t0x00000100\n\t\t\t\t\t\t\t\t\t\t\t/* support for holes */\n#    define CRAMFS_FLAG_WRONG_SIGNATURE\t0x00000200\n\t\t\t\t\t\t\t\t\t\t\t\t/* reserved */\n#    define CRAMFS_FLAG_SHIFTED_ROOT_OFFSET\t0x00000400\n\t\t\t\t\t\t\t\t\t\t\t\t\t/* shifted root fs */\n\n/*\n * Valid values in super.flags.  Currently we refuse to mount\n * if (flags & ~CRAMFS_SUPPORTED_FLAGS).  Maybe that should be\n * changed to test super.future instead.\n */\n#    define CRAMFS_SUPPORTED_FLAGS\t( 0x000000ff \\\n\t\t\t\t| CRAMFS_FLAG_HOLES \\\n\t\t\t\t| CRAMFS_FLAG_WRONG_SIGNATURE \\\n\t\t\t\t| CRAMFS_FLAG_SHIFTED_ROOT_OFFSET )\n\n#endif /* __CRAMFS_FS_H */\n"
  },
  {
    "path": "include/cramfs/cramfsswap.h",
    "content": "#ifndef __CRAMFSSWAP_H\n#define __CRAMFSSWAP_H\nint cramswap(char *sinfile, char *soutfile);\n#endif //__CRAMFSSWAP_H\n"
  },
  {
    "path": "include/crc.h",
    "content": "/*\n**  CRC.H - header file for SNIPPETS CRC and checksum functions\n*/\n\n#ifndef CRC__H\n#    define CRC__H\n\n#    include <stdlib.h>\t\t\t/* For size_t                 */\n#    include \"sniptype.h\"\t\t/* For BYTE, WORD, DWORD      */\n\n/*\n**  File: ARCCRC16.C\n*/\n\nvoid init_crc_table(void);\nWORD crc_calc(WORD crc, char *buf, unsigned nbytes);\nvoid do_file(char *fn);\n\n/*\n**  File: CRC-16.C\n*/\n\nWORD crc16(char *data_p, WORD length);\n\n/*\n**  File: CRC-16F.C\n*/\n\nWORD updcrc(WORD icrc, BYTE * icp, size_t icnt);\n\n/*\n**  File: CRC_32.C\n*/\n\n#    define UPDC32(octet,crc) (crc_32_tab[((crc)\\\n     ^ ((BYTE)octet)) & 0xff] ^ ((crc) >> 8))\n\nDWORD updateCRC32(unsigned char ch, DWORD crc);\nBoolean_T crc32file(char *name, DWORD * crc, long *charcnt);\nDWORD crc32buf(char *buf, size_t len);\n\n/*\n**  File: CHECKSUM.C\n*/\n\nunsigned checksum(void *buffer, size_t len, unsigned int seed);\n\n/*\n**  File: CHECKEXE.C\n*/\n\nvoid checkexe(char *fname);\n\n#endif /* CRC__H */\n"
  },
  {
    "path": "include/epk.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n\n#ifndef __EPK_H\n#define __EPK_H\n#include <inttypes.h>\n#include <stdint.h>\n#include <stdbool.h>\n\n#define SIGNATURE_SIZE 0x80  //RSA-1024\n#define SIGNATURE_SIZE_NEW 0x100 //RSA-2048\ntypedef unsigned char signature_t[SIGNATURE_SIZE];\ntypedef unsigned char signature_new_t[SIGNATURE_SIZE_NEW];\n\ntypedef enum {\n\tRELEASE = 0,\n\tDEBUG,\n\tTEST,\n\tUNKNOWN,\n} BUILD_TYPE_T;\n\ntypedef enum {\n    EPK,\n\tEPK_V2,\n\tEPK_V3,\n\tEPK_V3_NEW,\n    PAK_V2,\n    RAW\n} FILE_TYPE_T;\n\ntypedef enum {\n\tSIG_SHA1,\n\tSIG_SHA256\n} SIG_TYPE_T;\n\n#define EPK_VERSION_FORMAT \"%02\" PRIx8 \".%02\" PRIx8 \".%02\" PRIx8 \".%02\" PRIx8\n#define EPKV1_VERSION_FORMAT \"%02\" PRIx8 \".%02\" PRIx8 \".%02\" PRIx8\n\nbool isEpkVersionString(const char *str);\nint wrap_verifyimage(void *signature, void *data, size_t signSize, char *config_dir, SIG_TYPE_T sigType);\nint wrap_decryptimage(void *src, size_t datalen, void *dest, char *config_dir, FILE_TYPE_T type, FILE_TYPE_T *outType);\nvoid extractEPKfile(const char *epk_file, config_opts_t *config_opts);\n#endif\n"
  },
  {
    "path": "include/epk1.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * Copyright 20?? sirius\n * All right reserved\n */\n\n#ifndef EPK1_H_\n#    define EPK1_H_\n\n#    include <stdint.h>\n#    include <sys/stat.h>\n#    include <sys/types.h>\n#    include <stdio.h>\n#    include <epk.h>\n#    include <string.h>\n\nstruct pakRec_t {\n\tuint32_t offset;\n\tuint32_t size;\n};\n\nstruct epk1BEHeader_t {\n\tunsigned char epakMagic[4];\n\tuint32_t fileSize;\n\tuint32_t pakCount;\n\tuint32_t offset;\n\tuint32_t size;\n};\n\nstruct epk1BEVersion_t {\n\tuint8_t pad;\n\tuint8_t major;\n\tuint8_t minor1;\n\tuint8_t minor2;\n};\n\nstruct epk1Header_t {\n\tunsigned char epakMagic[4];\n\tuint32_t fileSize;\n\tuint32_t pakCount;\n\tstruct pakRec_t pakRecs[20];\n\tunsigned char fwVer[4];\n\tunsigned char otaID[32];\n};\n\nstruct epk1NewHeader_t {\n\tunsigned char epakMagic[4];\n\tuint32_t fileSize;\n\tuint32_t pakCount;\n\tunsigned char fwVer[4];\n\tunsigned char otaID[32];\n\tstruct pakRec_t pakRecs[26];\n};\n\nstruct pakHeader_t {\n\tunsigned char pakName[4];\n\tuint32_t pakSize;\n\tunsigned char platform[15];\n\tunsigned char unknown[105];\n};\n\nvoid extract_epk1_file(const char *epk_file, config_opts_t *config_opts);\nbool isFileEPK1(const char *epk_file);\n\n#endif /* EPK1_H_ */\n"
  },
  {
    "path": "include/epk2.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#ifndef _EPK2_H_\n#define _EPK2_H_\n\n#include <stdint.h>\n#include \"mfile.h\"\n#include \"epk.h\"\n\n#define EPK2_MAGIC \"EPK2\"\n#define PAK_MAGIC \"MPAK\"\n\nint compare_pak2_header(uint8_t *header, size_t headerSize);\nint compare_epk2_header(uint8_t *header, size_t headerSize);\nMFILE *isFileEPK2(const char *epk_file);\nvoid extractEPK2(MFILE *epk, config_opts_t *config_opts);\n\ntypedef struct {\n\tchar imageType[4];\n\tuint32_t imageSize; //excluded headers and signatures\n\tchar modelName[64];\n\tuint32_t swVersion;\n\tuint32_t swDate;\n\tBUILD_TYPE_T devMode;\n\tuint32_t segmentCount;\n\tuint32_t segmentSize;\n\tuint32_t segmentIndex;\n\tchar pakMagic[4];\n\tunsigned char reserved[24];\n\tuint32_t segmentCrc32;\n} PAK_V2_HEADER_T;\n\ntypedef struct {\n\tuint32_t imageOffset;\n\tuint32_t imageSize; //containing headers (excluded signatures)\n\tchar imageType[4];\n\tuint32_t imageVersion;\n\tuint32_t segmentSize;\n} PAK_V2_LOCATION_T;\n\n/**\n * NOTE: the number of partitions is hardcoded in the structure\n * 16 - GP2\n * 32 - (not sure if some sets use 32)\n * 64 - NC4\n **/\ntypedef struct {\n\tchar fileType[4];\n\tuint32_t fileSize;\n\tuint32_t fileNum;\n\tchar epkMagic[4];\n\tuint8_t epakVersion[4];\n\tchar otaId[32];\n\tPAK_V2_LOCATION_T imageLocation[64];\n} EPK_V2_HEADER_T;\n\nstruct epk2_structure {\n\tsignature_t signature;\n\tEPK_V2_HEADER_T epkHeader;\n\tuint32_t crc32Info[64];\n\tuint32_t reserved;\n\tchar platformVersion[16];\n\tchar sdkVersion[16];\n};\n\nstruct pak2_structure {\n\tsignature_t signature;\n\tPAK_V2_HEADER_T pakHeader;\n\tunsigned char pData[];\n};\n#endif\n"
  },
  {
    "path": "include/epk3.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n\n#ifndef __EPK3_H\n#define __EPK3_H\n#include \"mfile.h\"\n#include \"epk.h\"\n\n#define EPK3_MAGIC \"EPK3\"\n\nint compare_epk3_header(uint8_t *header, size_t headerSize);\nint compare_epk3_new_header(uint8_t *header, size_t headerSize);\nMFILE *isFileEPK3(const char *epk_file);\nvoid extractEPK3(MFILE *epk, FILE_TYPE_T epkType, config_opts_t *config_opts);\n\ntypedef struct __attribute__((packed)) {\n\tchar epkMagic[4];\n\tuint8_t epkVersion[4];\n\tchar otaId[32];\n\tuint32_t packageInfoSize;\n\tuint32_t bChunked;\n} EPK_V3_HEADER_T;\n\ntypedef struct __attribute__((packed)) {\n\tchar epkMagic[4];\n\tchar epkVersion[4];\n\tchar otaId[32];\n\tuint32_t packageInfoSize;\n\tuint32_t bChunked;\n\tuint32_t pakInfoMagic;\n\tuint8_t encryptType[6];\n\tuint8_t updateType[3];\n\tuint8_t gap[3];\n\tfloat updatePlatformVersion;\n\tfloat compatibleMinimumVersion;\n\tint needToCheckCompatibleVersion;\n\tuint8_t reserved[1384];\n} EPK_V3_NEW_HEADER_T;\n\ntypedef union __attribute__((packed)) {\n\tEPK_V3_HEADER_T old;\n\tEPK_V3_NEW_HEADER_T new;\n} EPK_V3_HEADER_UNION;\n\ntypedef struct __attribute__((packed)) {\n\t// SegmentInfo\n\tuint32_t isSegmented;\n\tuint32_t segmentIndex;\n\tuint32_t segmentCount;\n\tuint32_t segmentSize;\n} PACKAGE_SEGMENT_INFO_T;\n\ntypedef struct __attribute__((packed)) {\n\t// PackageData\n\t//void * pData;\n\tuint32_t reserved;\n} PACKAGE_INFO_DATA_T;\n\ntypedef struct __attribute__((packed)) {\n\t// PackageInfo\n\tuint32_t packageType;\n\tuint32_t packageInfoSize;\n\tchar packageName[128];\n\tchar packageVersion[96];\n\tchar packageArchitecture[32];\n\tunsigned char checkSum[32];\n\tuint32_t packageSize;\n\tuint32_t dipk;\n\tPACKAGE_SEGMENT_INFO_T segmentInfo;\n\tPACKAGE_INFO_DATA_T infoData;\n} PAK_V3_HEADER_T;\n\ntypedef struct __attribute__((packed)) {\n\t// ListHeader\n\tuint32_t packageInfoListSize;\n\tuint32_t packageInfoCount;\n\tPAK_V3_HEADER_T packages[];\n} PAK_V3_LISTHEADER_T;\n\ntypedef struct __attribute__((packed)) {\n\tuint32_t packageInfoListSize;\n\tuint32_t packageInfoCount;\n\tuint32_t pakInfoMagic;\n\tPAK_V3_HEADER_T packages[];\n} PAK_V3_NEW_LISTHEADER_T;\n\ntypedef union __attribute__((packed)) {\n\tPAK_V3_LISTHEADER_T old;\n\tPAK_V3_NEW_LISTHEADER_T new;\n} PAK_V3_LISTHEADER_UNION;\n\nstruct __attribute__((packed)) epk3_head_structure {\n\tsignature_t signature;\n\tEPK_V3_HEADER_T epkHeader;\n\tuint32_t crc32Info[384];\n\tuint32_t reserved; //or unknown\n\tchar platformVersion[16];\n\tchar sdkVersion[16];\n};\n\nstruct __attribute__((packed)) epk3_new_head_structure {\n\tsignature_new_t signature;\n\tEPK_V3_NEW_HEADER_T epkHeader;\n\tchar platformVersion[16];\n\tchar sdkVersion[16];\n};\n\nstruct  __attribute__((packed)) epk3_structure {\n\tstruct epk3_head_structure head;\n\tsignature_t packageInfo_signature;\n\tPAK_V3_LISTHEADER_T packageInfo;\n};\n\nstruct __attribute__((packed)) epk3_new_structure {\n\tstruct epk3_new_head_structure head;\n\tsignature_new_t packageInfo_signature;\n\tPAK_V3_NEW_LISTHEADER_T packageInfo;\n};\n\ntypedef union __attribute__((packed)) {\n\tstruct epk3_structure old;\n\tstruct epk3_new_structure new;\n} epk3_union;\n\nstruct __attribute__((packed)) pak3_structure {\n\tsignature_t signature;\n\tPAK_V3_HEADER_T header;\n};\n#endif\n"
  },
  {
    "path": "include/jffs2/jffs2.h",
    "content": "/*\n * JFFS2 -- Journalling Flash File System, Version 2.\n *\n * Copyright © 2001-2007 Red Hat, Inc.\n * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>\n *\n * Created by David Woodhouse <dwmw2@infradead.org>\n *\n * For licensing information, see the file 'LICENCE' in the\n * jffs2 directory.\n */\n\n#ifndef __LINUX_JFFS2_H__\n#define __LINUX_JFFS2_H__\n\n#ifdef __APPLE__\ntypedef __signed__ char __s8;\ntypedef unsigned char __u8;\n\ntypedef __signed__ short __s16;\ntypedef unsigned short __u16;\n\ntypedef __signed__ int __s32;\ntypedef unsigned int __u32;\n\n#ifdef __GNUC__\n__extension__ typedef __signed__ long long __s64;\n__extension__ typedef unsigned long long __u64;\n#else\ntypedef __signed__ long long __s64;\ntypedef unsigned long long __u64;\n#endif\n#else\n#include <asm/types.h>\n#endif\n\n/* Values we may expect to find in the 'magic' field */\n#define JFFS2_OLD_MAGIC_BITMASK 0x1984\n#define JFFS2_MAGIC_BITMASK 0x1985\n#define KSAMTIB_CIGAM_2SFFJ 0x8519 /* For detecting wrong-endian fs */\n#define JFFS2_EMPTY_BITMASK 0xffff\n#define JFFS2_DIRTY_BITMASK 0x0000\n\n/* Summary node MAGIC marker */\n#define JFFS2_SUM_MAGIC\t0x02851885\n\n/* We only allow a single char for length, and 0xFF is empty flash so\n   we don't want it confused with a real length. Hence max 254.\n*/\n#define JFFS2_MAX_NAME_LEN 254\n\n/* How small can we sensibly write nodes? */\n#define JFFS2_MIN_DATA_LEN 128\n\n#define JFFS2_COMPR_NONE\t0x00\n#define JFFS2_COMPR_ZERO\t0x01\n#define JFFS2_COMPR_RTIME\t0x02\n#define JFFS2_COMPR_RUBINMIPS\t0x03\n#define JFFS2_COMPR_COPY\t0x04\n#define JFFS2_COMPR_DYNRUBIN\t0x05\n#define JFFS2_COMPR_ZLIB\t0x06\n#define JFFS2_COMPR_LZO\t\t0x07\n#define JFFS2_COMPR_LZMA\t0x08\n/* Compatibility flags. */\n#define JFFS2_COMPAT_MASK 0xc000      /* What do to if an unknown nodetype is found */\n#define JFFS2_NODE_ACCURATE 0x2000\n/* INCOMPAT: Fail to mount the filesystem */\n#define JFFS2_FEATURE_INCOMPAT 0xc000\n/* ROCOMPAT: Mount read-only */\n#define JFFS2_FEATURE_ROCOMPAT 0x8000\n/* RWCOMPAT_COPY: Mount read/write, and copy the node when it's GC'd */\n#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000\n/* RWCOMPAT_DELETE: Mount read/write, and delete the node when it's GC'd */\n#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000\n\n#define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1)\n#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2)\n#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)\n#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4)\n\n#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)\n\n#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8)\n#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)\n\n/* XATTR Related */\n#define JFFS2_XPREFIX_USER\t\t1\t/* for \"user.\" */\n#define JFFS2_XPREFIX_SECURITY\t\t2\t/* for \"security.\" */\n#define JFFS2_XPREFIX_ACL_ACCESS\t3\t/* for \"system.posix_acl_access\" */\n#define JFFS2_XPREFIX_ACL_DEFAULT\t4\t/* for \"system.posix_acl_default\" */\n#define JFFS2_XPREFIX_TRUSTED\t\t5\t/* for \"trusted.*\" */\n\n#define JFFS2_ACL_VERSION\t\t0x0001\n\n// Maybe later...\n//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)\n//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)\n\n\n#define JFFS2_INO_FLAG_PREREAD\t  1\t/* Do read_inode() for this one at\n\t\t\t\t\t   mount time, don't wait for it to\n\t\t\t\t\t   happen later */\n#define JFFS2_INO_FLAG_USERCOMPR  2\t/* User has requested a specific\n\t\t\t\t\t   compression type */\n\n\nstruct jffs2_unknown_node\n{\n\t/* All start like this */\n\t__u16 magic;\n\t__u16 nodetype;\n\t__u32 totlen; /* So we can skip over nodes we don't grok */\n\t__u32 hdr_crc;\n};\n\nstruct jffs2_raw_dirent\n{\n\t__u16 magic;\n\t__u16 nodetype;\t/* == JFFS2_NODETYPE_DIRENT */\n\t__u32 totlen;\n\t__u32 hdr_crc;\n\t__u32 pino;\n\t__u32 version;\n\t__u32 ino; /* == zero for unlink */\n\t__u32 mctime;\n\t__u8 nsize;\n\t__u8 type;\n\t__u8 unused[2];\n\t__u32 node_crc;\n\t__u32 name_crc;\n\t__u8 name[0];\n};\n\n/* The JFFS2 raw inode structure: Used for storage on physical media.  */\n/* The uid, gid, atime, mtime and ctime members could be longer, but\n   are left like this for space efficiency. If and when people decide\n   they really need them extended, it's simple enough to add support for\n   a new type of raw node.\n*/\nstruct jffs2_raw_inode\n{\n\t__u16 magic;      /* A constant magic number.  */\n\t__u16 nodetype;   /* == JFFS2_NODETYPE_INODE */\n\t__u32 totlen;     /* Total length of this node (inc data, etc.) */\n\t__u32 hdr_crc;\n\t__u32 ino;        /* Inode number.  */\n\t__u32 version;    /* Version number.  */\n\t__u32 mode;       /* The file's type or mode.  */\n\t__u16 uid;        /* The file's owner.  */\n\t__u16 gid;        /* The file's group.  */\n\t__u32 isize;      /* Total resultant size of this inode (used for truncations)  */\n\t__u32 atime;      /* Last access time.  */\n\t__u32 mtime;      /* Last modification time.  */\n\t__u32 ctime;      /* Change time.  */\n\t__u32 offset;     /* Where to begin to write.  */\n\t__u32 csize;      /* (Compressed) data size */\n\t__u32 dsize;\t     /* Size of the node's data. (after decompression) */\n\t__u8 compr;       /* Compression algorithm used */\n\t__u8 usercompr;   /* Compression algorithm requested by the user */\n\t__u16 flags;\t     /* See JFFS2_INO_FLAG_* */\n\t__u32 data_crc;   /* CRC for the (compressed) data.  */\n\t__u32 node_crc;   /* CRC for the raw inode (excluding data)  */\n\t__u8 data[0];\n};\n\nstruct jffs2_raw_xattr {\n\t__u16 magic;\n\t__u16 nodetype;\t/* = JFFS2_NODETYPE_XATTR */\n\t__u32 totlen;\n\t__u32 hdr_crc;\n\t__u32 xid;\t\t/* XATTR identifier number */\n\t__u32 version;\n\t__u8 xprefix;\n\t__u8 name_len;\n\t__u16 value_len;\n\t__u32 data_crc;\n\t__u32 node_crc;\n\t__u8 data[0];\n} __attribute__((packed));\n\nstruct jffs2_raw_xref\n{\n\t__u16 magic;\n\t__u16 nodetype;\t/* = JFFS2_NODETYPE_XREF */\n\t__u32 totlen;\n\t__u32 hdr_crc;\n\t__u32 ino;\t\t/* inode number */\n\t__u32 xid;\t\t/* XATTR identifier number */\n\t__u32 xseqno;\t/* xref sequential number */\n\t__u32 node_crc;\n} __attribute__((packed));\n\nstruct jffs2_raw_summary\n{\n\t__u16 magic;\n\t__u16 nodetype; \t/* = JFFS2_NODETYPE_SUMMARY */\n\t__u32 totlen;\n\t__u32 hdr_crc;\n\t__u32 sum_num;\t/* number of sum entries*/\n\t__u32 cln_mkr;\t/* clean marker size, 0 = no cleanmarker */\n\t__u32 padded;\t/* sum of the size of padding nodes */\n\t__u32 sum_crc;\t/* summary information crc */\n\t__u32 node_crc; \t/* node crc */\n\t__u32 sum[0]; \t/* inode summary info */\n};\n\nunion jffs2_node_union\n{\n\tstruct jffs2_raw_inode i;\n\tstruct jffs2_raw_dirent d;\n\tstruct jffs2_raw_xattr x;\n\tstruct jffs2_raw_xref r;\n\tstruct jffs2_raw_summary s;\n\tstruct jffs2_unknown_node u;\n};\n\n/* Data payload for device nodes. */\nunion jffs2_device_node {\n\t__u16 old_id;\n\t__u32 new_id;\n};\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdbool.h>\n\nstruct jffs2_main_args {\n\tint erase_size;\n\tint verbose;\n\tbool keep_unlinked;\n};\n\nint jffs2extract(char *infile, char *outdir, struct jffs2_main_args);\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __LINUX_JFFS2_H__ */\n"
  },
  {
    "path": "include/jffs2/mini_inflate.h",
    "content": "/*-------------------------------------------------------------------------\n * Filename:      mini_inflate.h\n * Version:       $Id: mini_inflate.h,v 1.2 2002/01/17 00:53:20 nyet Exp $\n * Copyright:     Copyright (C) 2001, Russ Dill\n * Author:        Russ Dill <Russ.Dill@asu.edu>\n * Description:   Mini deflate implementation\n *-----------------------------------------------------------------------*/\n/*\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n */\n\ntypedef __SIZE_TYPE__ size;\n\n#define NO_ERROR 0\n#define COMP_UNKNOWN 1\t\t\t/* The specififed bytype is invalid */\n#define CODE_NOT_FOUND 2\t\t/* a huffman code in the stream could not be decoded */\n#define TOO_MANY_BITS 3\t\t\t/* pull_bits was passed an argument that is too\n\t\t\t\t\t\t\t\t * large */\n\n/* This struct represents an entire huffman code set. It has various lookup\n * tables to speed decoding */\nstruct huffman_set {\n\tint bits;\t\t\t\t\t/* maximum bit length */\n\tint num_symbols;\t\t\t/* Number of symbols this code can represent */\n\tint *lengths;\t\t\t\t/* The bit length of symbols */\n\tint *symbols;\t\t\t\t/* All of the symbols, sorted by the huffman code */\n\tint *count;\t\t\t\t\t/* the number of codes of this bit length */\n\tint *first;\t\t\t\t\t/* the first code of this bit length */\n\tint *pos;\t\t\t\t\t/* the symbol that first represents (in the symbols\n\t\t\t\t\t\t\t\t * array) */\n};\n\nstruct bitstream {\n\tunsigned char *data;\t\t/* increments as we move from byte to byte */\n\tunsigned char bit;\t\t\t/* 0 to 7 */\n\tvoid *(*memcpy) (void *, const void *, size);\n\tunsigned long decoded;\t\t/* The number of bytes decoded */\n\tint error;\n\n\tint distance_count[16];\n\tint distance_first[16];\n\tint distance_pos[16];\n\tint distance_lengths[32];\n\tint distance_symbols[32];\n\n\tint code_count[8];\n\tint code_first[8];\n\tint code_pos[8];\n\tint code_lengths[19];\n\tint code_symbols[19];\n\n\tint length_count[16];\n\tint length_first[16];\n\tint length_pos[16];\n\tint length_lengths[288];\n\tint length_symbols[288];\n\n\tstruct huffman_set codes;\n\tstruct huffman_set lengths;\n\tstruct huffman_set distance;\n};\n\n#define NO_COMP 0\n#define FIXED_COMP 1\n#define DYNAMIC_COMP 2\n\nlong decompress_block(unsigned char *dest, unsigned char *source, void *(*inflate_memcpy) (void *dest, const void *src, size n));\n"
  },
  {
    "path": "include/log.h",
    "content": "#ifndef _LOG_H_\n#    define _LOG_H_\n/*\n* Copyright (c) 2011 Roman Tokarev <roman.s.tokarev@gmail.com>\n* All rights reserved.\n*\n* Redistribution and use in source and binary forms, with or without\n* modification, are permitted provided that the following conditions\n* are met:\n* 1. Redistributions of source code must retain the above copyright\n* notice, this list of conditions and the following disclaimer.\n* 2. Redistributions in binary form must reproduce the above copyright\n* notice, this list of conditions and the following disclaimer in the\n* documentation and/or other materials provided with the distribution.\n* 3. Neither the name of the author nor the names of any co-contributors\n* may be used to endorse or promote products derived from this software\n* without specific prior written permission.\n*\n* THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS\n* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n* ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY\n* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\n* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\n* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#    define error_level 0\n#    define info_level 1\n#    define debug_level 2\n\n#    define say_error(format, args...) say(error_level, \"error: \"format, ##args)\n#    define say_info(format, args...) say(info_level, \"info: \"format, ##args)\n#    define say_debug(format, args...) say(debug_level, \"debug: \"format, ##args)\n\nextern unsigned verbose;\n\nint create_log(const char *fname);\nvoid say(unsigned level, const char *format, ...);\n\n#endif\n"
  },
  {
    "path": "include/lz4/bench.h",
    "content": "/*\n    bench.h - Demo program to benchmark open-source compression algorithm\n    Copyright (C) Yann Collet 2012\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (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    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n\tYou can contact the author at :\n\t- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\n\t- LZ4 source repository : http://code.google.com/p/lz4/\n*/\n#pragma once\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\tint BMK_benchFile(char **fileNamesTable, int nbFiles, int cLevel);\n\n// Parameters\n\tvoid BMK_SetBlocksize(int bsize);\n\tvoid BMK_SetNbIterations(int nbLoops);\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "include/lz4/lz4.h",
    "content": "/*\n   LZ4 - Fast LZ compression algorithm\n   Header File\n   Copyright (C) 2011-2012, Yann Collet.\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\n   - LZ4 source repository : http://code.google.com/p/lz4/\n*/\n#pragma once\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n//****************************\n// Simple Functions\n//****************************\n\nint LZ4_compress(const char *source, char *dest, int isize);\nint LZ4_uncompress(const char *source, char *dest, int osize);\n\nint LZ4_decode_file(const char *input_filename, const char *output_filename);\n\n/*\nLZ4_compress() :\n\tisize  : is the input size. Max supported value is ~1.9GB\n\treturn : the number of bytes written in buffer dest\n\t\t\t or 0 if the compression fails (if LZ4_COMPRESSMIN is set)\n\tnote : destination buffer must be already allocated.\n\t\tdestination buffer must be sized to handle worst cases situations (input data not compressible)\n\t\tworst case size evaluation is provided by function LZ4_compressBound()\n\nLZ4_uncompress() :\n\tosize  : is the output size, therefore the original size\n\treturn : the number of bytes read in the source buffer\n\t\t\t If the source stream is malformed, the function will stop decoding and return a negative result, indicating the byte position of the faulty instruction\n\t\t\t This function never writes beyond dest + osize, and is therefore protected against malicious data packets\n\tnote : destination buffer must be already allocated\n*/\n\n//****************************\n// Advanced Functions\n//****************************\n\nint LZ4_compressBound(int isize);\n\n/*\nLZ4_compressBound() :\n\tProvides the maximum size that LZ4 may output in a \"worst case\" scenario (input data not compressible)\n\tprimarily useful for memory allocation of output buffer.\n\n\tisize  : is the input size. Max supported value is ~1.9GB\n\treturn : maximum output size in a \"worst case\" scenario\n\tnote : this function is limited by \"int\" range (2^31-1)\n*/\n\nint LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize, int maxOutputSize);\n\n/*\nLZ4_uncompress_unknownOutputSize() :\n\tisize  : is the input size, therefore the compressed size\n\tmaxOutputSize : is the size of the destination buffer (which must be already allocated)\n\treturn : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize)\n\t\t\t If the source stream is malformed, the function will stop decoding and return a negative result, indicating the byte position of the faulty instruction\n\t\t\t This function never writes beyond dest + maxOutputSize, and is therefore protected against malicious data packets\n\tnote   : Destination buffer must be already allocated.\n\t         This version is slightly slower than LZ4_uncompress()\n*/\n\nint LZ4_compressCtx(void **ctx, const char *source, char *dest, int isize);\nint LZ4_compress64kCtx(void **ctx, const char *source, char *dest, int isize);\n\n/*\nLZ4_compressCtx() :\n\tThis function explicitly handles the CTX memory structure.\n\tIt avoids allocating/deallocating memory between each call, improving performance when malloc is heavily invoked.\n\tThis function is only useful when memory is allocated into the heap (HASH_LOG value beyond STACK_LIMIT)\n\tPerformance difference will be noticeable only when repetitively calling the compression function over many small segments.\n\tNote : by default, memory is allocated into the stack, therefore \"malloc\" is not invoked.\nLZ4_compress64kCtx() :\n\tSame as LZ4_compressCtx(), but specific to small inputs (<64KB).\n\tisize *Must* be <64KB, otherwise the output will be corrupted.\n\n\tOn first call : provide a *ctx=NULL; It will be automatically allocated.\n\tOn next calls : reuse the same ctx pointer.\n\tUse different pointers for different threads when doing multi-threading.\n\n*/\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "include/lz4/lz4hc.h",
    "content": "/*\n   LZ4 HC - High Compression Mode of LZ4\n   Header File\n   Copyright (C) 2011-2012, Yann Collet.\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\n   - LZ4 source repository : http://code.google.com/p/lz4/\n*/\n#pragma once\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\tint LZ4_compressHC(const char *source, char *dest, int isize);\n\n/*\nLZ4_compressHC :\n\treturn : the number of bytes in compressed buffer dest\n\tnote : destination buffer must be already allocated.\n\t\tTo avoid any problem, size it to handle worst cases situations (input data not compressible)\n\t\tWorst case size evaluation is provided by function LZ4_compressBound() (see \"lz4.h\")\n*/\n\n/* Note :\nDecompression functions are provided within regular LZ4 source code (see \"lz4.h\") (BSD license)\n*/\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "include/lzhs/lzhs.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * All right reserved\n */\n#ifndef _LZHS_H\n#define _LZHS_H\n\n#include <stdint.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include \"mfile.h\"\n\nstruct lzhs_header {\n\tuint32_t uncompressedSize, compressedSize;\n\tuint16_t checksum; /* checksum is 1 byte, segment number is 2 bytes */\n\tuint8_t spare[6];\n};\n\n/* for LZSS */\n#define N             4096\n#define F             34\n#define THRESHOLD     2\n\nstruct lzhs_ctx {\n\t/* LZSS  */\n\tunsigned long int textsize, codesize;\n\tuint8_t text_buf[N + F - 1];\n\tint32_t match_length, match_position, lson[N + 1], rson[N + 257], dad[N + 1];\n\n\t/* Huffman  */\n\tint32_t i, j, k;\n\tuint32_t c, code, len, code_buf_ptr;\n\tuint8_t code_buf[32], mask, bitno;\n\tuint32_t preno, precode;\n};\n\n/*for Huffman */\ntypedef struct __attribute__ ((__packed__)) {\n\tuint32_t code;\n\tuint32_t len;\n} t_code;\n\nstruct lzhs_ctx *lzhs_ctx_new();\nvoid lzhs_init_lookup();\nvoid unlzss(struct lzhs_ctx *ctx, cursor_t *in, cursor_t *out);\nvoid unhuff(struct lzhs_ctx *ctx, cursor_t *in, cursor_t *out);\n\nMFILE *is_lzhs(const char *filename);\nbool _is_lzhs_mem(struct lzhs_header *header);\nbool is_lzhs_mem(MFILE *file, off_t offset);\n\nvoid lzss(struct lzhs_ctx *ctx, FILE * infile, FILE * outfile, unsigned long int *p_textsize, unsigned long int *p_codesize);\nvoid huff(struct lzhs_ctx *ctx, FILE * in, FILE * out, unsigned long int *p_textsize, unsigned long int *p_codesize);\n\nint process_lzhs_segment(MFILE *in_file, off_t offset, const char *name);\n\nint extract_lzhs(MFILE *in_file);\ncursor_t *lzhs_decode(MFILE *in_file, off_t offset, const char *out_path, uint8_t *out_checksum);\nvoid lzhs_encode(const char *infile, const char *outfile);\nvoid scan_lzhs(const char *filename, int extract);\n\n#endif\n"
  },
  {
    "path": "include/lzhs/tables.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * All right reserved\n */\n#ifndef _LZHS_TAB_H\n#    define _LZHS_TAB_H\nstatic uint8_t charlen_table[2304] = {\t//256 + 32 elements of t_code\n\t0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,\n\t0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0x29, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0x2B, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0x2D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0x2F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x8B, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x8D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x90, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x91, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x82, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x83, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x93, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x0B, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x85, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0x33, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x96, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x87, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x34, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x99, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x9A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x8A, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x35, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x9D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x8D, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8E, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x8F, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x9E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x91, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x92, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x93, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x94, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x96, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x36, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x37, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0x98, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x99, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xA0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x9A, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x39, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0x3B, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xA2, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0x9B, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9C, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x9D, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9E, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x9F, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA0, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xA1, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB0, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xB1, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xB2, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xA2, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA3, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xA4, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB3, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xA5, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB4, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xB5, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xB6, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0x3C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xA5, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xA7, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xA6, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB7, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xA7, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA8, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xA9, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAA, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xAB, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAC, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0x3D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xAD, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xAA, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xAF, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xB8, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xB9, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0x3E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xB1, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xB2, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB3, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xBA, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xBB, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xBC, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xBD, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0x3F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xB4, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB5, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xB6, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBE, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xBF, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xAC, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xB7, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xB9, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC1, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xC2, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xC3, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xAE, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xB0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xC4, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xC5, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xC6, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xC7, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xC8, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0x40, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xBA, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBB, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xC9, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xCA, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xCB, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xCC, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xB2, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xCD, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xCE, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xCF, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xD0, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xD1, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xDE, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xB4, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xBC, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xBD, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBE, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xD2, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xD3, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xDF, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xB5, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xD5, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE1, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xD6, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xD7, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE2, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xD8, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE3, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xE4, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xE5, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xD9, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xE6, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xE7, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xB8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xBF, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xDA, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xDB, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xDC, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE8, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xE9, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xEA, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xC0, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC1, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xDD, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xEB, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xDE, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xEC, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xED, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xEE, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0x0E, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0xC2, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC3, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xDF, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xC4, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xEF, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xC5, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC6, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xE0, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE1, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xC7, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE2, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xF1, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xF2, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC8, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xC9, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE3, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xE4, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xCA, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xCB, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0xCC, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCD, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xCE, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE5, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xE6, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE7, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xE8, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE9, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0x42, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xF3, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xF4, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xEA, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xF5, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xCF, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xBA, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xD1, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xD2, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD3, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xD4, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xBB, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,\n\t0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,\n\t0xBC, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,\n\t0xBE, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xD6, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,\n\t0xD7, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEB, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xEC, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xED, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,\n\t0xEE, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xF6, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xF7, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xF9, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xFA, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,\n\t0xFB, 0x07, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,\n\t0xF9, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xFA, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,\n\t0xFB, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,\n\t0xFC, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xFD, 0x1F, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,\n\t0xFD, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0x1F, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,\n\t0xFF, 0x1F, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00\n};\n\nstatic uint8_t pos_table[256] = {\t\t//32 elements of t_code\n\t0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,\n\t0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,\n\t0x0F, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,\n\t0x11, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,\n\t0x13, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,\n\t0x2A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x2C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x2E, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x32, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x34, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x38, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x3A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x3C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,\n\t0x3E, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00\n};\n#endif\n"
  },
  {
    "path": "include/lzma/LzFind.h",
    "content": "/* LzFind.h -- Match finder for LZ algorithms\n2009-04-22 : Igor Pavlov : Public domain */\n\n#ifndef __LZ_FIND_H\n#define __LZ_FIND_H\n\n#include \"Types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef UInt32 CLzRef;\n\ntypedef struct _CMatchFinder\n{\n  Byte *buffer;\n  UInt32 pos;\n  UInt32 posLimit;\n  UInt32 streamPos;\n  UInt32 lenLimit;\n\n  UInt32 cyclicBufferPos;\n  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */\n\n  UInt32 matchMaxLen;\n  CLzRef *hash;\n  CLzRef *son;\n  UInt32 hashMask;\n  UInt32 cutValue;\n\n  Byte *bufferBase;\n  ISeqInStream *stream;\n  int streamEndWasReached;\n\n  UInt32 blockSize;\n  UInt32 keepSizeBefore;\n  UInt32 keepSizeAfter;\n\n  UInt32 numHashBytes;\n  int directInput;\n  size_t directInputRem;\n  int btMode;\n  int bigHash;\n  UInt32 historySize;\n  UInt32 fixedHashSize;\n  UInt32 hashSizeSum;\n  UInt32 numSons;\n  SRes result;\n  UInt32 crc[256];\n} CMatchFinder;\n\n#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)\n#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])\n\n#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)\n\nint MatchFinder_NeedMove(CMatchFinder *p);\nByte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);\nvoid MatchFinder_MoveBlock(CMatchFinder *p);\nvoid MatchFinder_ReadIfRequired(CMatchFinder *p);\n\nvoid MatchFinder_Construct(CMatchFinder *p);\n\n/* Conditions:\n     historySize <= 3 GB\n     keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB\n*/\nint MatchFinder_Create(CMatchFinder *p, UInt32 historySize,\n    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,\n    ISzAlloc *alloc);\nvoid MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);\nvoid MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);\nvoid MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);\n\nUInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,\n    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,\n    UInt32 *distances, UInt32 maxLen);\n\n/*\nConditions:\n  Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.\n  Mf_GetPointerToCurrentPos_Func's result must be used only before any other function\n*/\n\ntypedef void (*Mf_Init_Func)(void *object);\ntypedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);\ntypedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);\ntypedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);\ntypedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);\ntypedef void (*Mf_Skip_Func)(void *object, UInt32);\n\ntypedef struct _IMatchFinder\n{\n  Mf_Init_Func Init;\n  Mf_GetIndexByte_Func GetIndexByte;\n  Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;\n  Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;\n  Mf_GetMatches_Func GetMatches;\n  Mf_Skip_Func Skip;\n} IMatchFinder;\n\nvoid MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);\n\nvoid MatchFinder_Init(CMatchFinder *p);\nUInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);\nUInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);\nvoid Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);\nvoid Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/lzma/LzHash.h",
    "content": "/* LzHash.h -- HASH functions for LZ algorithms\n2009-02-07 : Igor Pavlov : Public domain */\n\n#ifndef __LZ_HASH_H\n#define __LZ_HASH_H\n\n#define kHash2Size (1 << 10)\n#define kHash3Size (1 << 16)\n#define kHash4Size (1 << 20)\n\n#define kFix3HashSize (kHash2Size)\n#define kFix4HashSize (kHash2Size + kHash3Size)\n#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)\n\n#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);\n\n#define HASH3_CALC { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  hash2Value = temp & (kHash2Size - 1); \\\n  hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }\n\n#define HASH4_CALC { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  hash2Value = temp & (kHash2Size - 1); \\\n  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \\\n  hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }\n\n#define HASH5_CALC { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  hash2Value = temp & (kHash2Size - 1); \\\n  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \\\n  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \\\n  hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \\\n  hash4Value &= (kHash4Size - 1); }\n\n/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */\n#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;\n\n\n#define MT_HASH2_CALC \\\n  hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);\n\n#define MT_HASH3_CALC { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  hash2Value = temp & (kHash2Size - 1); \\\n  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }\n\n#define MT_HASH4_CALC { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  hash2Value = temp & (kHash2Size - 1); \\\n  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \\\n  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }\n\n#endif\n"
  },
  {
    "path": "include/lzma/LzmaDec.h",
    "content": "/* LzmaDec.h -- LZMA Decoder\n2009-02-07 : Igor Pavlov : Public domain */\n\n#ifndef __LZMA_DEC_H\n#define __LZMA_DEC_H\n\n#include \"Types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* #define _LZMA_PROB32 */\n/* _LZMA_PROB32 can increase the speed on some CPUs,\n   but memory usage for CLzmaDec::probs will be doubled in that case */\n\n#ifdef _LZMA_PROB32\n#define CLzmaProb UInt32\n#else\n#define CLzmaProb UInt16\n#endif\n\n\n/* ---------- LZMA Properties ---------- */\n\n#define LZMA_PROPS_SIZE 5\n\ntypedef struct _CLzmaProps\n{\n  unsigned lc, lp, pb;\n  UInt32 dicSize;\n} CLzmaProps;\n\n/* LzmaProps_Decode - decodes properties\nReturns:\n  SZ_OK\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n*/\n\nSRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);\n\n\n/* ---------- LZMA Decoder state ---------- */\n\n/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.\n   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */\n\n#define LZMA_REQUIRED_INPUT_MAX 20\n\ntypedef struct\n{\n  CLzmaProps prop;\n  CLzmaProb *probs;\n  Byte *dic;\n  const Byte *buf;\n  UInt32 range, code;\n  SizeT dicPos;\n  SizeT dicBufSize;\n  UInt32 processedPos;\n  UInt32 checkDicSize;\n  unsigned state;\n  UInt32 reps[4];\n  unsigned remainLen;\n  int needFlush;\n  int needInitState;\n  UInt32 numProbs;\n  unsigned tempBufSize;\n  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];\n} CLzmaDec;\n\n#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }\n\nvoid LzmaDec_Init(CLzmaDec *p);\n\n/* There are two types of LZMA streams:\n     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.\n     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */\n\ntypedef enum\n{\n  LZMA_FINISH_ANY,   /* finish at any point */\n  LZMA_FINISH_END    /* block must be finished at the end */\n} ELzmaFinishMode;\n\n/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!\n\n   You must use LZMA_FINISH_END, when you know that current output buffer\n   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.\n\n   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,\n   and output value of destLen will be less than output buffer size limit.\n   You can check status result also.\n\n   You can use multiple checks to test data integrity after full decompression:\n     1) Check Result and \"status\" variable.\n     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.\n     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.\n        You must use correct finish mode in that case. */\n\ntypedef enum\n{\n  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */\n  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */\n  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */\n  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */\n  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */\n} ELzmaStatus;\n\n/* ELzmaStatus is used only as output value for function call */\n\n\n/* ---------- Interfaces ---------- */\n\n/* There are 3 levels of interfaces:\n     1) Dictionary Interface\n     2) Buffer Interface\n     3) One Call Interface\n   You can select any of these interfaces, but don't mix functions from different\n   groups for same object. */\n\n\n/* There are two variants to allocate state for Dictionary Interface:\n     1) LzmaDec_Allocate / LzmaDec_Free\n     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs\n   You can use variant 2, if you set dictionary buffer manually.\n   For Buffer Interface you must always use variant 1.\n\nLzmaDec_Allocate* can return:\n  SZ_OK\n  SZ_ERROR_MEM         - Memory allocation error\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n*/\n\nSRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);\nvoid LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);\n\nSRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);\nvoid LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);\n\n/* ---------- Dictionary Interface ---------- */\n\n/* You can use it, if you want to eliminate the overhead for data copying from\n   dictionary to some other external buffer.\n   You must work with CLzmaDec variables directly in this interface.\n\n   STEPS:\n     LzmaDec_Constr()\n     LzmaDec_Allocate()\n     for (each new stream)\n     {\n       LzmaDec_Init()\n       while (it needs more decompression)\n       {\n         LzmaDec_DecodeToDic()\n         use data from CLzmaDec::dic and update CLzmaDec::dicPos\n       }\n     }\n     LzmaDec_Free()\n*/\n\n/* LzmaDec_DecodeToDic\n\n   The decoding to internal dictionary buffer (CLzmaDec::dic).\n   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!\n\nfinishMode:\n  It has meaning only if the decoding reaches output limit (dicLimit).\n  LZMA_FINISH_ANY - Decode just dicLimit bytes.\n  LZMA_FINISH_END - Stream must be finished after dicLimit.\n\nReturns:\n  SZ_OK\n    status:\n      LZMA_STATUS_FINISHED_WITH_MARK\n      LZMA_STATUS_NOT_FINISHED\n      LZMA_STATUS_NEEDS_MORE_INPUT\n      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\n  SZ_ERROR_DATA - Data error\n*/\n\nSRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,\n    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\n\n\n/* ---------- Buffer Interface ---------- */\n\n/* It's zlib-like interface.\n   See LzmaDec_DecodeToDic description for information about STEPS and return results,\n   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need\n   to work with CLzmaDec variables manually.\n\nfinishMode:\n  It has meaning only if the decoding reaches output limit (*destLen).\n  LZMA_FINISH_ANY - Decode just destLen bytes.\n  LZMA_FINISH_END - Stream must be finished after (*destLen).\n*/\n\nSRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,\n    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\n\n\n/* ---------- One Call Interface ---------- */\n\n/* LzmaDecode\n\nfinishMode:\n  It has meaning only if the decoding reaches output limit (*destLen).\n  LZMA_FINISH_ANY - Decode just destLen bytes.\n  LZMA_FINISH_END - Stream must be finished after (*destLen).\n\nReturns:\n  SZ_OK\n    status:\n      LZMA_STATUS_FINISHED_WITH_MARK\n      LZMA_STATUS_NOT_FINISHED\n      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\n  SZ_ERROR_DATA - Data error\n  SZ_ERROR_MEM  - Memory allocation error\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).\n*/\n\nSRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,\n    ELzmaStatus *status, ISzAlloc *alloc);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/lzma/LzmaEnc.h",
    "content": "/*  LzmaEnc.h -- LZMA Encoder\n2009-02-07 : Igor Pavlov : Public domain */\n\n#ifndef __LZMA_ENC_H\n#define __LZMA_ENC_H\n\n#include \"Types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define LZMA_PROPS_SIZE 5\n\ntypedef struct _CLzmaEncProps\n{\n  int level;       /*  0 <= level <= 9 */\n  UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version\n                      (1 << 12) <= dictSize <= (1 << 30) for 64-bit version\n                       default = (1 << 24) */\n  int lc;          /* 0 <= lc <= 8, default = 3 */\n  int lp;          /* 0 <= lp <= 4, default = 0 */\n  int pb;          /* 0 <= pb <= 4, default = 2 */\n  int algo;        /* 0 - fast, 1 - normal, default = 1 */\n  int fb;          /* 5 <= fb <= 273, default = 32 */\n  int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */\n  int numHashBytes; /* 2, 3 or 4, default = 4 */\n  UInt32 mc;        /* 1 <= mc <= (1 << 30), default = 32 */\n  unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */\n  int numThreads;  /* 1 or 2, default = 2 */\n} CLzmaEncProps;\n\nvoid LzmaEncProps_Init(CLzmaEncProps *p);\nvoid LzmaEncProps_Normalize(CLzmaEncProps *p);\nUInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);\n\n\n/* ---------- CLzmaEncHandle Interface ---------- */\n\n/* LzmaEnc_* functions can return the following exit codes:\nReturns:\n  SZ_OK           - OK\n  SZ_ERROR_MEM    - Memory allocation error\n  SZ_ERROR_PARAM  - Incorrect paramater in props\n  SZ_ERROR_WRITE  - Write callback error.\n  SZ_ERROR_PROGRESS - some break from progress callback\n  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)\n*/\n\ntypedef void * CLzmaEncHandle;\n\nCLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);\nvoid LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);\nSRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);\nSRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);\nSRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,\n    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);\nSRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\n    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);\n\n/* ---------- One Call Interface ---------- */\n\n/* LzmaEncode\nReturn code:\n  SZ_OK               - OK\n  SZ_ERROR_MEM        - Memory allocation error\n  SZ_ERROR_PARAM      - Incorrect paramater\n  SZ_ERROR_OUTPUT_EOF - output buffer overflow\n  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)\n*/\n\nSRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\n    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,\n    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/lzma/Types.h",
    "content": "/* Types.h -- Basic types\n2009-11-23 : Igor Pavlov : Public domain */\n\n#ifndef __7Z_TYPES_H\n#define __7Z_TYPES_H\n\n#include <stddef.h>\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\n#ifndef EXTERN_C_BEGIN\n#ifdef __cplusplus\n#define EXTERN_C_BEGIN extern \"C\" {\n#define EXTERN_C_END }\n#else\n#define EXTERN_C_BEGIN\n#define EXTERN_C_END\n#endif\n#endif\n\nEXTERN_C_BEGIN\n\n#define SZ_OK 0\n\n#define SZ_ERROR_DATA 1\n#define SZ_ERROR_MEM 2\n#define SZ_ERROR_CRC 3\n#define SZ_ERROR_UNSUPPORTED 4\n#define SZ_ERROR_PARAM 5\n#define SZ_ERROR_INPUT_EOF 6\n#define SZ_ERROR_OUTPUT_EOF 7\n#define SZ_ERROR_READ 8\n#define SZ_ERROR_WRITE 9\n#define SZ_ERROR_PROGRESS 10\n#define SZ_ERROR_FAIL 11\n#define SZ_ERROR_THREAD 12\n\n#define SZ_ERROR_ARCHIVE 16\n#define SZ_ERROR_NO_ARCHIVE 17\n\ntypedef int SRes;\n\n#ifdef _WIN32\ntypedef DWORD WRes;\n#else\ntypedef int WRes;\n#endif\n\n#ifndef RINOK\n#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }\n#endif\n\ntypedef unsigned char Byte;\ntypedef short Int16;\ntypedef unsigned short UInt16;\n\n#ifdef _LZMA_UINT32_IS_ULONG\ntypedef long Int32;\ntypedef unsigned long UInt32;\n#else\ntypedef int Int32;\ntypedef unsigned int UInt32;\n#endif\n\n#ifdef _SZ_NO_INT_64\n\n/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.\n   NOTES: Some code will work incorrectly in that case! */\n\ntypedef long Int64;\ntypedef unsigned long UInt64;\n\n#else\n\n#if defined(_MSC_VER) || defined(__BORLANDC__)\ntypedef __int64 Int64;\ntypedef unsigned __int64 UInt64;\n#else\ntypedef long long int Int64;\ntypedef unsigned long long int UInt64;\n#endif\n\n#endif\n\n#ifdef _LZMA_NO_SYSTEM_SIZE_T\ntypedef UInt32 SizeT;\n#else\ntypedef size_t SizeT;\n#endif\n\ntypedef int Bool;\n#define True 1\n#define False 0\n\n\n#ifdef _WIN32\n#define MY_STD_CALL __stdcall\n#else\n#define MY_STD_CALL\n#endif\n\n#ifdef _MSC_VER\n\n#if _MSC_VER >= 1300\n#define MY_NO_INLINE __declspec(noinline)\n#else\n#define MY_NO_INLINE\n#endif\n\n#define MY_CDECL __cdecl\n#define MY_FAST_CALL __fastcall\n\n#else\n\n#define MY_CDECL\n#define MY_FAST_CALL\n\n#endif\n\n\n/* The following interfaces use first parameter as pointer to structure */\n\ntypedef struct\n{\n  SRes (*Read)(void *p, void *buf, size_t *size);\n    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.\n       (output(*size) < input(*size)) is allowed */\n} ISeqInStream;\n\n/* it can return SZ_ERROR_INPUT_EOF */\nSRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);\nSRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);\nSRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);\n\ntypedef struct\n{\n  size_t (*Write)(void *p, const void *buf, size_t size);\n    /* Returns: result - the number of actually written bytes.\n       (result < size) means error */\n} ISeqOutStream;\n\ntypedef enum\n{\n  SZ_SEEK_SET = 0,\n  SZ_SEEK_CUR = 1,\n  SZ_SEEK_END = 2\n} ESzSeek;\n\ntypedef struct\n{\n  SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */\n  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);\n} ISeekInStream;\n\ntypedef struct\n{\n  SRes (*Look)(void *p, void **buf, size_t *size);\n    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.\n       (output(*size) > input(*size)) is not allowed\n       (output(*size) < input(*size)) is allowed */\n  SRes (*Skip)(void *p, size_t offset);\n    /* offset must be <= output(*size) of Look */\n\n  SRes (*Read)(void *p, void *buf, size_t *size);\n    /* reads directly (without buffer). It's same as ISeqInStream::Read */\n  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);\n} ILookInStream;\n\nSRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);\nSRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);\n\n/* reads via ILookInStream::Read */\nSRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);\nSRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);\n\n#define LookToRead_BUF_SIZE (1 << 14)\n\ntypedef struct\n{\n  ILookInStream s;\n  ISeekInStream *realStream;\n  size_t pos;\n  size_t size;\n  Byte buf[LookToRead_BUF_SIZE];\n} CLookToRead;\n\nvoid LookToRead_CreateVTable(CLookToRead *p, int lookahead);\nvoid LookToRead_Init(CLookToRead *p);\n\ntypedef struct\n{\n  ISeqInStream s;\n  ILookInStream *realStream;\n} CSecToLook;\n\nvoid SecToLook_CreateVTable(CSecToLook *p);\n\ntypedef struct\n{\n  ISeqInStream s;\n  ILookInStream *realStream;\n} CSecToRead;\n\nvoid SecToRead_CreateVTable(CSecToRead *p);\n\ntypedef struct\n{\n  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);\n    /* Returns: result. (result != SZ_OK) means break.\n       Value (UInt64)(Int64)-1 for size means unknown value. */\n} ICompressProgress;\n\ntypedef struct\n{\n  void *(*Alloc)(void *p, size_t size);\n  void (*Free)(void *p, void *address); /* address can be 0 */\n} ISzAlloc;\n\n#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)\n#define IAlloc_Free(p, a) (p)->Free((p), a)\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "include/lzma.h",
    "content": "#pragma once\n\n#include <stdint.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <string.h>\n#include <errno.h>\n#include \"jffs2/jffs2.h\"\n#ifndef PAGE_SIZE\n\textern int page_size;\n\t#define PAGE_SIZE page_size\n#endif\n#define LZMA_MALLOC malloc\n#define LZMA_FREE free\n#define PRINT_ERROR(msg) fprintf(stderr, msg)\n#define INIT\n#define STATIC\n\n#ifndef __APPLE__\n#    include <asm/types.h>\n#endif\n\n#include \"lzma/LzmaDec.h\"\n#include \"lzma/LzmaEnc.h\"\n\n#define LZMA_BEST_LEVEL (9)\n#define LZMA_BEST_LC    (0)\n#define LZMA_BEST_LP    (0)\n#define LZMA_BEST_PB    (0)\n#define LZMA_BEST_FB  (273)\n\n#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2)\n\nstatic void *p_lzma_malloc(void *p, size_t size)\n{\n        if (size == 0)\n                return NULL;\n\n        return LZMA_MALLOC(size);\n}\n\nstatic void p_lzma_free(void *p, void *address)\n{\n        if (address != NULL)\n                LZMA_FREE(address);\n}\n\nstatic ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free};\n\n"
  },
  {
    "path": "include/lzo/lzo.h",
    "content": "#ifndef __LZO_LG_H\n#define __LZO_LG_H\nint check_lzo_header(const char *name);\nint lzo_unpack(const char *in_name, const char *out_name);\n#endif //__LZO_LG_H\n"
  },
  {
    "path": "include/lzo/miniacc.h",
    "content": "/* ACC --- Automatic Compiler Configuration\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n   All Rights Reserved.\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU General Public License as\n   published by the Free Software Foundation; either version 2 of\n   the License, or (at your option) any later version.\n\n   The LZO library 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   You should have received a copy of the GNU General Public License\n   along with the LZO library; see the file COPYING.\n   If not, write to the Free Software Foundation, Inc.,\n   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\n   Markus F.X.J. Oberhumer\n   <markus@oberhumer.com>\n   http://www.oberhumer.com/opensource/lzo/\n */\n\n#ifndef __ACC_H_INCLUDED\n#    define __ACC_H_INCLUDED 1\n#    define ACC_VERSION     20080430L\n#    if defined(__CYGWIN32__) && !defined(__CYGWIN__)\n#        define __CYGWIN__ __CYGWIN32__\n#    endif\n#    if defined(__IBMCPP__) && !defined(__IBMC__)\n#        define __IBMC__ __IBMCPP__\n#    endif\n#    if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)\n#        define __INTEL_COMPILER __ICL\n#    endif\n#    if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)\n#        define _ALL_SOURCE 1\n#    endif\n#    if defined(__mips__) && defined(__R5900__)\n#        if !defined(__LONG_MAX__)\n#            define __LONG_MAX__ 9223372036854775807L\n#        endif\n#    endif\n#    if defined(__INTEL_COMPILER) && defined(__linux__)\n#        pragma warning(disable: 193)\n#    endif\n#    if defined(__KEIL__) && defined(__C166__)\n#        pragma warning disable = 322\n#    elif 0 && defined(__C251__)\n#        pragma warning disable = 322\n#    endif\n#    if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)\n#        if (_MSC_VER >= 1300)\n#            pragma warning(disable: 4668)\n#        endif\n#    endif\n#    if defined(__POCC__) && defined(_WIN32)\n#        if (__POCC__ >= 400)\n#            pragma warn(disable: 2216)\n#        endif\n#    endif\n#    if 0 && defined(__WATCOMC__)\n#        if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)\n#            pragma warning 203 9\n#        endif\n#    endif\n#    if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)\n#        pragma option -h\n#    endif\n#    if defined(ACC_CFG_NO_CONFIG_HEADER)\n#    elif defined(ACC_CFG_CONFIG_HEADER)\n#        include ACC_CFG_CONFIG_HEADER\n#    else\n#    endif\n#    if defined(ACC_CFG_NO_LIMITS_H)\n#    elif defined(ACC_LIBC_NAKED) || defined(ACC_BROKEN_LIMITS_H)\n#        ifndef __ACC_FALLBACK_LIMITS_H_INCLUDED\n#            define __ACC_FALLBACK_LIMITS_H_INCLUDED\n#            undef CHAR_BIT\n#            define CHAR_BIT        8\n#            ifndef MB_LEN_MAX\n#                define MB_LEN_MAX      1\n#            endif\n#            ifndef __SCHAR_MAX__\n#                define __SCHAR_MAX__   127\n#            endif\n#            ifndef __SHRT_MAX__\n#                define __SHRT_MAX__    32767\n#            endif\n#            ifndef __INT_MAX__\n#                define __INT_MAX__     2147483647\n#            endif\n#            ifndef __LONG_MAX__\n#                if defined(__alpha__) || defined(_LP64) || defined(__MIPS_PSX2__)\n#                    define __LONG_MAX__    9223372036854775807L\n#                else\n#                    define __LONG_MAX__    2147483647L\n#                endif\n#            endif\n#            undef SCHAR_MIN\n#            undef SCHAR_MAX\n#            undef UCHAR_MAX\n#            define SCHAR_MIN       (-1 - SCHAR_MAX)\n#            define SCHAR_MAX       (__SCHAR_MAX__)\n#            define UCHAR_MAX       (SCHAR_MAX * 2 + 1)\n#            undef SHRT_MIN\n#            undef SHRT_MAX\n#            undef USHRT_MAX\n#            define SHRT_MIN        (-1 - SHRT_MAX)\n#            define SHRT_MAX        (__SHRT_MAX__)\n#            if ((__INT_MAX__) == (__SHRT_MAX__))\n#                define USHRT_MAX       (SHRT_MAX * 2U + 1U)\n#            else\n#                define USHRT_MAX       (SHRT_MAX * 2 + 1)\n#            endif\n#            undef INT_MIN\n#            undef INT_MAX\n#            undef UINT_MAX\n#            define INT_MIN         (-1 - INT_MAX)\n#            define INT_MAX         (__INT_MAX__)\n#            define UINT_MAX        (INT_MAX * 2U + 1U)\n#            undef LONG_MIN\n#            undef LONG_MAX\n#            undef ULONG_MAX\n#            define LONG_MIN        (-1L - LONG_MAX)\n#            define LONG_MAX        ((__LONG_MAX__) + 0L)\n#            define ULONG_MAX       (LONG_MAX * 2UL + 1UL)\n#            undef CHAR_MIN\n#            undef CHAR_MAX\n#            if defined(__CHAR_UNSIGNED__) || defined(_CHAR_UNSIGNED)\n#                define CHAR_MIN        0\n#                define CHAR_MAX        UCHAR_MAX\n#            else\n#                define CHAR_MIN        SCHAR_MIN\n#                define CHAR_MAX        SCHAR_MAX\n#            endif\n#        endif\n#    else\n#        include <limits.h>\n#    endif\n#    if 0\n#        define ACC_0xffffL             0xfffful\n#        define ACC_0xffffffffL         0xfffffffful\n#    else\n#        define ACC_0xffffL             65535ul\n#        define ACC_0xffffffffL         4294967295ul\n#    endif\n#    if (ACC_0xffffL == ACC_0xffffffffL)\n#        error \"your preprocessor is broken 1\"\n#    endif\n#    if (16ul * 16384ul != 262144ul)\n#        error \"your preprocessor is broken 2\"\n#    endif\n#    if 0\n#        if (32767 >= 4294967295ul)\n#            error \"your preprocessor is broken 3\"\n#        endif\n#        if (65535u >= 4294967295ul)\n#            error \"your preprocessor is broken 4\"\n#        endif\n#    endif\n#    if (UINT_MAX == ACC_0xffffL)\n#        if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)\n#            if !defined(MSDOS)\n#                define MSDOS 1\n#            endif\n#            if !defined(_MSDOS)\n#                define _MSDOS 1\n#            endif\n#        elif 0 && defined(__VERSION) && defined(MB_LEN_MAX)\n#            if (__VERSION == 520) && (MB_LEN_MAX == 1)\n#                if !defined(__AZTEC_C__)\n#                    define __AZTEC_C__ __VERSION\n#                endif\n#                if !defined(__DOS__)\n#                    define __DOS__ 1\n#                endif\n#            endif\n#        endif\n#    endif\n#    if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == ACC_0xffffL)\n#        define ptrdiff_t long\n#        define _PTRDIFF_T_DEFINED\n#    endif\n#    if (UINT_MAX == ACC_0xffffL)\n#        undef __ACC_RENAME_A\n#        undef __ACC_RENAME_B\n#        if defined(__AZTEC_C__) && defined(__DOS__)\n#            define __ACC_RENAME_A 1\n#        elif defined(_MSC_VER) && defined(MSDOS)\n#            if (_MSC_VER < 600)\n#                define __ACC_RENAME_A 1\n#            elif (_MSC_VER < 700)\n#                define __ACC_RENAME_B 1\n#            endif\n#        elif defined(__TSC__) && defined(__OS2__)\n#            define __ACC_RENAME_A 1\n#        elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410)\n#            define __ACC_RENAME_A 1\n#        elif defined(__PACIFIC__) && defined(DOS)\n#            if !defined(__far)\n#                define __far far\n#            endif\n#            if !defined(__near)\n#                define __near near\n#            endif\n#        endif\n#        if defined(__ACC_RENAME_A)\n#            if !defined(__cdecl)\n#                define __cdecl cdecl\n#            endif\n#            if !defined(__far)\n#                define __far far\n#            endif\n#            if !defined(__huge)\n#                define __huge huge\n#            endif\n#            if !defined(__near)\n#                define __near near\n#            endif\n#            if !defined(__pascal)\n#                define __pascal pascal\n#            endif\n#            if !defined(__huge)\n#                define __huge huge\n#            endif\n#        elif defined(__ACC_RENAME_B)\n#            if !defined(__cdecl)\n#                define __cdecl _cdecl\n#            endif\n#            if !defined(__far)\n#                define __far _far\n#            endif\n#            if !defined(__huge)\n#                define __huge _huge\n#            endif\n#            if !defined(__near)\n#                define __near _near\n#            endif\n#            if !defined(__pascal)\n#                define __pascal _pascal\n#            endif\n#        elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)\n#            if !defined(__cdecl)\n#                define __cdecl cdecl\n#            endif\n#            if !defined(__pascal)\n#                define __pascal pascal\n#            endif\n#        endif\n#        undef __ACC_RENAME_A\n#        undef __ACC_RENAME_B\n#    endif\n#    if (UINT_MAX == ACC_0xffffL)\n#        if defined(__AZTEC_C__) && defined(__DOS__)\n#            define ACC_BROKEN_CDECL_ALT_SYNTAX 1\n#        elif defined(_MSC_VER) && defined(MSDOS)\n#            if (_MSC_VER < 600)\n#                define ACC_BROKEN_INTEGRAL_CONSTANTS 1\n#            endif\n#            if (_MSC_VER < 700)\n#                define ACC_BROKEN_INTEGRAL_PROMOTION 1\n#                define ACC_BROKEN_SIZEOF 1\n#            endif\n#        elif defined(__PACIFIC__) && defined(DOS)\n#            define ACC_BROKEN_INTEGRAL_CONSTANTS 1\n#        elif defined(__TURBOC__) && defined(__MSDOS__)\n#            if (__TURBOC__ < 0x0150)\n#                define ACC_BROKEN_CDECL_ALT_SYNTAX 1\n#                define ACC_BROKEN_INTEGRAL_CONSTANTS 1\n#                define ACC_BROKEN_INTEGRAL_PROMOTION 1\n#            endif\n#            if (__TURBOC__ < 0x0200)\n#                define ACC_BROKEN_SIZEOF 1\n#            endif\n#            if (__TURBOC__ < 0x0400) && defined(__cplusplus)\n#                define ACC_BROKEN_CDECL_ALT_SYNTAX 1\n#            endif\n#        elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)\n#            define ACC_BROKEN_CDECL_ALT_SYNTAX 1\n#            define ACC_BROKEN_SIZEOF 1\n#        endif\n#    endif\n#    if defined(__WATCOMC__) && (__WATCOMC__ < 900)\n#        define ACC_BROKEN_INTEGRAL_CONSTANTS 1\n#    endif\n#    if defined(_CRAY) && defined(_CRAY1)\n#        define ACC_BROKEN_SIGNED_RIGHT_SHIFT 1\n#    endif\n#    define ACC_PP_STRINGIZE(x)             #x\n#    define ACC_PP_MACRO_EXPAND(x)          ACC_PP_STRINGIZE(x)\n#    define ACC_PP_CONCAT2(a,b)             a ## b\n#    define ACC_PP_CONCAT3(a,b,c)           a ## b ## c\n#    define ACC_PP_CONCAT4(a,b,c,d)         a ## b ## c ## d\n#    define ACC_PP_CONCAT5(a,b,c,d,e)       a ## b ## c ## d ## e\n#    define ACC_PP_ECONCAT2(a,b)            ACC_PP_CONCAT2(a,b)\n#    define ACC_PP_ECONCAT3(a,b,c)          ACC_PP_CONCAT3(a,b,c)\n#    define ACC_PP_ECONCAT4(a,b,c,d)        ACC_PP_CONCAT4(a,b,c,d)\n#    define ACC_PP_ECONCAT5(a,b,c,d,e)      ACC_PP_CONCAT5(a,b,c,d,e)\n#    if 1\n#        define ACC_CPP_STRINGIZE(x)            #x\n#        define ACC_CPP_MACRO_EXPAND(x)         ACC_CPP_STRINGIZE(x)\n#        define ACC_CPP_CONCAT2(a,b)            a ## b\n#        define ACC_CPP_CONCAT3(a,b,c)          a ## b ## c\n#        define ACC_CPP_CONCAT4(a,b,c,d)        a ## b ## c ## d\n#        define ACC_CPP_CONCAT5(a,b,c,d,e)      a ## b ## c ## d ## e\n#        define ACC_CPP_ECONCAT2(a,b)           ACC_CPP_CONCAT2(a,b)\n#        define ACC_CPP_ECONCAT3(a,b,c)         ACC_CPP_CONCAT3(a,b,c)\n#        define ACC_CPP_ECONCAT4(a,b,c,d)       ACC_CPP_CONCAT4(a,b,c,d)\n#        define ACC_CPP_ECONCAT5(a,b,c,d,e)     ACC_CPP_CONCAT5(a,b,c,d,e)\n#    endif\n#    define __ACC_MASK_GEN(o,b)     (((((o) << ((b)-1)) - (o)) << 1) + (o))\n#    if 1 && defined(__cplusplus)\n#        if !defined(__STDC_CONSTANT_MACROS)\n#            define __STDC_CONSTANT_MACROS 1\n#        endif\n#        if !defined(__STDC_LIMIT_MACROS)\n#            define __STDC_LIMIT_MACROS 1\n#        endif\n#    endif\n#    if defined(__cplusplus)\n#        define ACC_EXTERN_C extern \"C\"\n#    else\n#        define ACC_EXTERN_C extern\n#    endif\n#    if !defined(__ACC_OS_OVERRIDE)\n#        if defined(ACC_OS_FREESTANDING)\n#            define ACC_INFO_OS           \"freestanding\"\n#        elif defined(ACC_OS_EMBEDDED)\n#            define ACC_INFO_OS           \"embedded\"\n#        elif 1 && defined(__IAR_SYSTEMS_ICC__)\n#            define ACC_OS_EMBEDDED       1\n#            define ACC_INFO_OS           \"embedded\"\n#        elif defined(__CYGWIN__) && defined(__GNUC__)\n#            define ACC_OS_CYGWIN         1\n#            define ACC_INFO_OS           \"cygwin\"\n#        elif defined(__EMX__) && defined(__GNUC__)\n#            define ACC_OS_EMX            1\n#            define ACC_INFO_OS           \"emx\"\n#        elif defined(__BEOS__)\n#            define ACC_OS_BEOS           1\n#            define ACC_INFO_OS           \"beos\"\n#        elif defined(__Lynx__)\n#            define ACC_OS_LYNXOS         1\n#            define ACC_INFO_OS           \"lynxos\"\n#        elif defined(__OS400__)\n#            define ACC_OS_OS400          1\n#            define ACC_INFO_OS           \"os400\"\n#        elif defined(__QNX__)\n#            define ACC_OS_QNX            1\n#            define ACC_INFO_OS           \"qnx\"\n#        elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460)\n#            define ACC_OS_DOS32          1\n#            define ACC_INFO_OS           \"dos32\"\n#        elif defined(__BORLANDC__) && defined(__DPMI16__)\n#            define ACC_OS_DOS16          1\n#            define ACC_INFO_OS           \"dos16\"\n#        elif defined(__ZTC__) && defined(DOS386)\n#            define ACC_OS_DOS32          1\n#            define ACC_INFO_OS           \"dos32\"\n#        elif defined(__OS2__) || defined(__OS2V2__)\n#            if (UINT_MAX == ACC_0xffffL)\n#                define ACC_OS_OS216        1\n#                define ACC_INFO_OS         \"os216\"\n#            elif (UINT_MAX == ACC_0xffffffffL)\n#                define ACC_OS_OS2          1\n#                define ACC_INFO_OS         \"os2\"\n#            else\n#                error \"check your limits.h header\"\n#            endif\n#        elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64)\n#            define ACC_OS_WIN64          1\n#            define ACC_INFO_OS           \"win64\"\n#        elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__)\n#            define ACC_OS_WIN32          1\n#            define ACC_INFO_OS           \"win32\"\n#        elif defined(__MWERKS__) && defined(__INTEL__)\n#            define ACC_OS_WIN32          1\n#            define ACC_INFO_OS           \"win32\"\n#        elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)\n#            if (UINT_MAX == ACC_0xffffL)\n#                define ACC_OS_WIN16        1\n#                define ACC_INFO_OS         \"win16\"\n#            elif (UINT_MAX == ACC_0xffffffffL)\n#                define ACC_OS_WIN32        1\n#                define ACC_INFO_OS         \"win32\"\n#            else\n#                error \"check your limits.h header\"\n#            endif\n#        elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS))\n#            if (UINT_MAX == ACC_0xffffL)\n#                define ACC_OS_DOS16        1\n#                define ACC_INFO_OS         \"dos16\"\n#            elif (UINT_MAX == ACC_0xffffffffL)\n#                define ACC_OS_DOS32        1\n#                define ACC_INFO_OS         \"dos32\"\n#            else\n#                error \"check your limits.h header\"\n#            endif\n#        elif defined(__WATCOMC__)\n#            if defined(__NT__) && (UINT_MAX == ACC_0xffffL)\n#                define ACC_OS_DOS16        1\n#                define ACC_INFO_OS         \"dos16\"\n#            elif defined(__NT__) && (__WATCOMC__ < 1100)\n#                define ACC_OS_WIN32        1\n#                define ACC_INFO_OS         \"win32\"\n#            elif defined(__linux__) || defined(__LINUX__)\n#                define ACC_OS_POSIX        1\n#                define ACC_INFO_OS         \"posix\"\n#            else\n#                error \"please specify a target using the -bt compiler option\"\n#            endif\n#        elif defined(__palmos__)\n#            define ACC_OS_PALMOS         1\n#            define ACC_INFO_OS           \"palmos\"\n#        elif defined(__TOS__) || defined(__atarist__)\n#            define ACC_OS_TOS            1\n#            define ACC_INFO_OS           \"tos\"\n#        elif defined(macintosh) && !defined(__ppc__)\n#            define ACC_OS_MACCLASSIC     1\n#            define ACC_INFO_OS           \"macclassic\"\n#        elif defined(__VMS)\n#            define ACC_OS_VMS            1\n#            define ACC_INFO_OS           \"vms\"\n#        elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))\n#            define ACC_OS_CONSOLE        1\n#            define ACC_OS_CONSOLE_PS2    1\n#            define ACC_INFO_OS           \"console\"\n#            define ACC_INFO_OS_CONSOLE   \"ps2\"\n#        elif (defined(__mips__) && defined(__psp__))\n#            define ACC_OS_CONSOLE        1\n#            define ACC_OS_CONSOLE_PSP    1\n#            define ACC_INFO_OS           \"console\"\n#            define ACC_INFO_OS_CONSOLE   \"psp\"\n#        else\n#            define ACC_OS_POSIX          1\n#            define ACC_INFO_OS           \"posix\"\n#        endif\n#        if (ACC_OS_POSIX)\n#            if defined(_AIX) || defined(__AIX__) || defined(__aix__)\n#                define ACC_OS_POSIX_AIX        1\n#                define ACC_INFO_OS_POSIX       \"aix\"\n#            elif defined(__FreeBSD__)\n#                define ACC_OS_POSIX_FREEBSD    1\n#                define ACC_INFO_OS_POSIX       \"freebsd\"\n#            elif defined(__hpux__) || defined(__hpux)\n#                define ACC_OS_POSIX_HPUX       1\n#                define ACC_INFO_OS_POSIX       \"hpux\"\n#            elif defined(__INTERIX)\n#                define ACC_OS_POSIX_INTERIX    1\n#                define ACC_INFO_OS_POSIX       \"interix\"\n#            elif defined(__IRIX__) || defined(__irix__)\n#                define ACC_OS_POSIX_IRIX       1\n#                define ACC_INFO_OS_POSIX       \"irix\"\n#            elif defined(__linux__) || defined(__linux) || defined(__LINUX__)\n#                define ACC_OS_POSIX_LINUX      1\n#                define ACC_INFO_OS_POSIX       \"linux\"\n#            elif defined(__APPLE__) || defined(__MACOS__)\n#                define ACC_OS_POSIX_MACOSX     1\n#                define ACC_INFO_OS_POSIX       \"macosx\"\n#            elif defined(__minix__) || defined(__minix)\n#                define ACC_OS_POSIX_MINIX      1\n#                define ACC_INFO_OS_POSIX       \"minix\"\n#            elif defined(__NetBSD__)\n#                define ACC_OS_POSIX_NETBSD     1\n#                define ACC_INFO_OS_POSIX       \"netbsd\"\n#            elif defined(__OpenBSD__)\n#                define ACC_OS_POSIX_OPENBSD    1\n#                define ACC_INFO_OS_POSIX       \"openbsd\"\n#            elif defined(__osf__)\n#                define ACC_OS_POSIX_OSF        1\n#                define ACC_INFO_OS_POSIX       \"osf\"\n#            elif defined(__solaris__) || defined(__sun)\n#                if defined(__SVR4) || defined(__svr4__)\n#                    define ACC_OS_POSIX_SOLARIS  1\n#                    define ACC_INFO_OS_POSIX     \"solaris\"\n#                else\n#                    define ACC_OS_POSIX_SUNOS    1\n#                    define ACC_INFO_OS_POSIX     \"sunos\"\n#                endif\n#            elif defined(__ultrix__) || defined(__ultrix)\n#                define ACC_OS_POSIX_ULTRIX     1\n#                define ACC_INFO_OS_POSIX       \"ultrix\"\n#            elif defined(_UNICOS)\n#                define ACC_OS_POSIX_UNICOS     1\n#                define ACC_INFO_OS_POSIX       \"unicos\"\n#            else\n#                define ACC_OS_POSIX_UNKNOWN    1\n#                define ACC_INFO_OS_POSIX       \"unknown\"\n#            endif\n#        endif\n#    endif\n#    if (ACC_OS_DOS16 || ACC_OS_OS216 || ACC_OS_WIN16)\n#        if (UINT_MAX != ACC_0xffffL)\n#            error \"this should not happen\"\n#        endif\n#        if (ULONG_MAX != ACC_0xffffffffL)\n#            error \"this should not happen\"\n#        endif\n#    endif\n#    if (ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_WIN32 || ACC_OS_WIN64)\n#        if (UINT_MAX != ACC_0xffffffffL)\n#            error \"this should not happen\"\n#        endif\n#        if (ULONG_MAX != ACC_0xffffffffL)\n#            error \"this should not happen\"\n#        endif\n#    endif\n#    if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)\n#        define ACC_CC_CILLY          1\n#        define ACC_INFO_CC           \"Cilly\"\n#        if defined(__CILLY__)\n#            define ACC_INFO_CCVER      ACC_PP_MACRO_EXPAND(__CILLY__)\n#        else\n#            define ACC_INFO_CCVER      \"unknown\"\n#        endif\n#    elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__)\n#        define ACC_CC_SDCC           1\n#        define ACC_INFO_CC           \"sdcc\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(SDCC)\n#    elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)\n#        define ACC_CC_PATHSCALE      (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)\n#        define ACC_INFO_CC           \"Pathscale C\"\n#        define ACC_INFO_CCVER        __PATHSCALE__\n#    elif defined(__INTEL_COMPILER)\n#        define ACC_CC_INTELC         1\n#        define ACC_INFO_CC           \"Intel C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__INTEL_COMPILER)\n#        if defined(_WIN32) || defined(_WIN64)\n#            define ACC_CC_SYNTAX_MSC 1\n#        else\n#            define ACC_CC_SYNTAX_GNUC 1\n#        endif\n#    elif defined(__POCC__) && defined(_WIN32)\n#        define ACC_CC_PELLESC        1\n#        define ACC_INFO_CC           \"Pelles C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__POCC__)\n#    elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__)\n#        if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)\n#            define ACC_CC_LLVM         (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)\n#        else\n#            define ACC_CC_LLVM         (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)\n#        endif\n#        define ACC_INFO_CC           \"llvm-gcc\"\n#        define ACC_INFO_CCVER        __VERSION__\n#    elif defined(__GNUC__) && defined(__VERSION__)\n#        if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)\n#            define ACC_CC_GNUC         (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)\n#        elif defined(__GNUC_MINOR__)\n#            define ACC_CC_GNUC         (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)\n#        else\n#            define ACC_CC_GNUC         (__GNUC__ * 0x10000L)\n#        endif\n#        define ACC_INFO_CC           \"gcc\"\n#        define ACC_INFO_CCVER        __VERSION__\n#    elif defined(__ACK__) && defined(_ACK)\n#        define ACC_CC_ACK            1\n#        define ACC_INFO_CC           \"Amsterdam Compiler Kit C\"\n#        define ACC_INFO_CCVER        \"unknown\"\n#    elif defined(__AZTEC_C__)\n#        define ACC_CC_AZTECC         1\n#        define ACC_INFO_CC           \"Aztec C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__AZTEC_C__)\n#    elif defined(__BORLANDC__)\n#        define ACC_CC_BORLANDC       1\n#        define ACC_INFO_CC           \"Borland C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__BORLANDC__)\n#    elif defined(_CRAYC) && defined(_RELEASE)\n#        define ACC_CC_CRAYC          1\n#        define ACC_INFO_CC           \"Cray C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(_RELEASE)\n#    elif defined(__DMC__) && defined(__SC__)\n#        define ACC_CC_DMC            1\n#        define ACC_INFO_CC           \"Digital Mars C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__DMC__)\n#    elif defined(__DECC)\n#        define ACC_CC_DECC           1\n#        define ACC_INFO_CC           \"DEC C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__DECC)\n#    elif defined(__HIGHC__)\n#        define ACC_CC_HIGHC          1\n#        define ACC_INFO_CC           \"MetaWare High C\"\n#        define ACC_INFO_CCVER        \"unknown\"\n#    elif defined(__IAR_SYSTEMS_ICC__)\n#        define ACC_CC_IARC           1\n#        define ACC_INFO_CC           \"IAR C\"\n#        if defined(__VER__)\n#            define ACC_INFO_CCVER      ACC_PP_MACRO_EXPAND(__VER__)\n#        else\n#            define ACC_INFO_CCVER      \"unknown\"\n#        endif\n#    elif defined(__IBMC__)\n#        define ACC_CC_IBMC           1\n#        define ACC_INFO_CC           \"IBM C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__IBMC__)\n#    elif defined(__KEIL__) && defined(__C166__)\n#        define ACC_CC_KEILC          1\n#        define ACC_INFO_CC           \"Keil C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__C166__)\n#    elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL)\n#        define ACC_CC_LCCWIN32       1\n#        define ACC_INFO_CC           \"lcc-win32\"\n#        define ACC_INFO_CCVER        \"unknown\"\n#    elif defined(__LCC__)\n#        define ACC_CC_LCC            1\n#        define ACC_INFO_CC           \"lcc\"\n#        if defined(__LCC_VERSION__)\n#            define ACC_INFO_CCVER      ACC_PP_MACRO_EXPAND(__LCC_VERSION__)\n#        else\n#            define ACC_INFO_CCVER      \"unknown\"\n#        endif\n#    elif defined(_MSC_VER)\n#        define ACC_CC_MSC            1\n#        define ACC_INFO_CC           \"Microsoft C\"\n#        if defined(_MSC_FULL_VER)\n#            define ACC_INFO_CCVER      ACC_PP_MACRO_EXPAND(_MSC_VER) \".\" ACC_PP_MACRO_EXPAND(_MSC_FULL_VER)\n#        else\n#            define ACC_INFO_CCVER      ACC_PP_MACRO_EXPAND(_MSC_VER)\n#        endif\n#    elif defined(__MWERKS__)\n#        define ACC_CC_MWERKS         1\n#        define ACC_INFO_CC           \"Metrowerks C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__MWERKS__)\n#    elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)\n#        define ACC_CC_NDPC           1\n#        define ACC_INFO_CC           \"Microway NDP C\"\n#        define ACC_INFO_CCVER        \"unknown\"\n#    elif defined(__PACIFIC__)\n#        define ACC_CC_PACIFICC       1\n#        define ACC_INFO_CC           \"Pacific C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__PACIFIC__)\n#    elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))\n#        define ACC_CC_PGI            1\n#        define ACC_INFO_CC           \"Portland Group PGI C\"\n#        define ACC_INFO_CCVER        \"unknown\"\n#    elif defined(__PUREC__) && defined(__TOS__)\n#        define ACC_CC_PUREC          1\n#        define ACC_INFO_CC           \"Pure C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__PUREC__)\n#    elif defined(__SC__) && defined(__ZTC__)\n#        define ACC_CC_SYMANTECC      1\n#        define ACC_INFO_CC           \"Symantec C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__SC__)\n#    elif defined(__SUNPRO_C)\n#        define ACC_INFO_CC           \"SunPro C\"\n#        if ((__SUNPRO_C)+0 > 0)\n#            define ACC_CC_SUNPROC      __SUNPRO_C\n#            define ACC_INFO_CCVER      ACC_PP_MACRO_EXPAND(__SUNPRO_C)\n#        else\n#            define ACC_CC_SUNPROC      1\n#            define ACC_INFO_CCVER      \"unknown\"\n#        endif\n#    elif defined(__SUNPRO_CC)\n#        define ACC_INFO_CC           \"SunPro C\"\n#        if ((__SUNPRO_CC)+0 > 0)\n#            define ACC_CC_SUNPROC      __SUNPRO_CC\n#            define ACC_INFO_CCVER      ACC_PP_MACRO_EXPAND(__SUNPRO_CC)\n#        else\n#            define ACC_CC_SUNPROC      1\n#            define ACC_INFO_CCVER      \"unknown\"\n#        endif\n#    elif defined(__TINYC__)\n#        define ACC_CC_TINYC          1\n#        define ACC_INFO_CC           \"Tiny C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__TINYC__)\n#    elif defined(__TSC__)\n#        define ACC_CC_TOPSPEEDC      1\n#        define ACC_INFO_CC           \"TopSpeed C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__TSC__)\n#    elif defined(__WATCOMC__)\n#        define ACC_CC_WATCOMC        1\n#        define ACC_INFO_CC           \"Watcom C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__WATCOMC__)\n#    elif defined(__TURBOC__)\n#        define ACC_CC_TURBOC         1\n#        define ACC_INFO_CC           \"Turbo C\"\n#        define ACC_INFO_CCVER        ACC_PP_MACRO_EXPAND(__TURBOC__)\n#    elif defined(__ZTC__)\n#        define ACC_CC_ZORTECHC       1\n#        define ACC_INFO_CC           \"Zortech C\"\n#        if (__ZTC__ == 0x310)\n#            define ACC_INFO_CCVER      \"0x310\"\n#        else\n#            define ACC_INFO_CCVER      ACC_PP_MACRO_EXPAND(__ZTC__)\n#        endif\n#    else\n#        define ACC_CC_UNKNOWN        1\n#        define ACC_INFO_CC           \"unknown\"\n#        define ACC_INFO_CCVER        \"unknown\"\n#    endif\n#    if 0 && (ACC_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)\n#        error \"ACC_CC_MSC: _MSC_FULL_VER is not defined\"\n#    endif\n#    if !defined(__ACC_ARCH_OVERRIDE) && !defined(ACC_ARCH_GENERIC) && defined(_CRAY)\n#        if (UINT_MAX > ACC_0xffffffffL) && defined(_CRAY)\n#            if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E)\n#                define ACC_ARCH_CRAY_MPP     1\n#            elif defined(_CRAY1)\n#                define ACC_ARCH_CRAY_PVP     1\n#            endif\n#        endif\n#    endif\n#    if !defined(__ACC_ARCH_OVERRIDE)\n#        if defined(ACC_ARCH_GENERIC)\n#            define ACC_INFO_ARCH             \"generic\"\n#        elif (ACC_OS_DOS16 || ACC_OS_OS216 || ACC_OS_WIN16)\n#            define ACC_ARCH_I086             1\n#            define ACC_ARCH_IA16             1\n#            define ACC_INFO_ARCH             \"i086\"\n#        elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)\n#            define ACC_ARCH_ALPHA            1\n#            define ACC_INFO_ARCH             \"alpha\"\n#        elif (ACC_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E))\n#            define ACC_ARCH_ALPHA            1\n#            define ACC_INFO_ARCH             \"alpha\"\n#        elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)\n#            define ACC_ARCH_AMD64            1\n#            define ACC_INFO_ARCH             \"amd64\"\n#        elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))\n#            define ACC_ARCH_ARM              1\n#            define ACC_ARCH_ARM_THUMB        1\n#            define ACC_INFO_ARCH             \"arm_thumb\"\n#        elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)\n#            define ACC_ARCH_ARM              1\n#            if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1)\n#                define ACC_ARCH_ARM_THUMB      1\n#                define ACC_INFO_ARCH           \"arm_thumb\"\n#            elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2)\n#                define ACC_INFO_ARCH           \"arm\"\n#            else\n#                define ACC_INFO_ARCH           \"arm\"\n#            endif\n#        elif defined(__arm__) || defined(_M_ARM)\n#            define ACC_ARCH_ARM              1\n#            define ACC_INFO_ARCH             \"arm\"\n#        elif (UINT_MAX <= ACC_0xffffL) && defined(__AVR__)\n#            define ACC_ARCH_AVR              1\n#            define ACC_INFO_ARCH             \"avr\"\n#        elif defined(__bfin__)\n#            define ACC_ARCH_BLACKFIN         1\n#            define ACC_INFO_ARCH             \"blackfin\"\n#        elif (UINT_MAX == ACC_0xffffL) && defined(__C166__)\n#            define ACC_ARCH_C166             1\n#            define ACC_INFO_ARCH             \"c166\"\n#        elif defined(__cris__)\n#            define ACC_ARCH_CRIS             1\n#            define ACC_INFO_ARCH             \"cris\"\n#        elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__)\n#            define ACC_ARCH_EZ80             1\n#            define ACC_INFO_ARCH             \"ez80\"\n#        elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)\n#            define ACC_ARCH_H8300            1\n#            define ACC_INFO_ARCH             \"h8300\"\n#        elif defined(__hppa__) || defined(__hppa)\n#            define ACC_ARCH_HPPA             1\n#            define ACC_INFO_ARCH             \"hppa\"\n#        elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)\n#            define ACC_ARCH_I386             1\n#            define ACC_ARCH_IA32             1\n#            define ACC_INFO_ARCH             \"i386\"\n#        elif (ACC_CC_ZORTECHC && defined(__I86__))\n#            define ACC_ARCH_I386             1\n#            define ACC_ARCH_IA32             1\n#            define ACC_INFO_ARCH             \"i386\"\n#        elif (ACC_OS_DOS32 && ACC_CC_HIGHC) && defined(_I386)\n#            define ACC_ARCH_I386             1\n#            define ACC_ARCH_IA32             1\n#            define ACC_INFO_ARCH             \"i386\"\n#        elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64)\n#            define ACC_ARCH_IA64             1\n#            define ACC_INFO_ARCH             \"ia64\"\n#        elif (UINT_MAX == ACC_0xffffL) && defined(__m32c__)\n#            define ACC_ARCH_M16C             1\n#            define ACC_INFO_ARCH             \"m16c\"\n#        elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__)\n#            define ACC_ARCH_M16C             1\n#            define ACC_INFO_ARCH             \"m16c\"\n#        elif defined(__m32r__)\n#            define ACC_ARCH_M32R             1\n#            define ACC_INFO_ARCH             \"m32r\"\n#        elif (ACC_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K)\n#            define ACC_ARCH_M68K             1\n#            define ACC_INFO_ARCH             \"m68k\"\n#        elif (UINT_MAX == ACC_0xffffL) && defined(__C251__)\n#            define ACC_ARCH_MCS251           1\n#            define ACC_INFO_ARCH             \"mcs251\"\n#        elif (UINT_MAX == ACC_0xffffL) && defined(__C51__)\n#            define ACC_ARCH_MCS51            1\n#            define ACC_INFO_ARCH             \"mcs51\"\n#        elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__)\n#            define ACC_ARCH_MCS51            1\n#            define ACC_INFO_ARCH             \"mcs51\"\n#        elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)\n#            define ACC_ARCH_MIPS             1\n#            define ACC_INFO_ARCH             \"mips\"\n#        elif (UINT_MAX == ACC_0xffffL) && defined(__MSP430__)\n#            define ACC_ARCH_MSP430           1\n#            define ACC_INFO_ARCH             \"msp430\"\n#        elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__)\n#            define ACC_ARCH_MSP430           1\n#            define ACC_INFO_ARCH             \"msp430\"\n#        elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)\n#            define ACC_ARCH_POWERPC          1\n#            define ACC_INFO_ARCH             \"powerpc\"\n#        elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)\n#            define ACC_ARCH_S390             1\n#            define ACC_INFO_ARCH             \"s390\"\n#        elif defined(__sh__) || defined(_M_SH)\n#            define ACC_ARCH_SH               1\n#            define ACC_INFO_ARCH             \"sh\"\n#        elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)\n#            define ACC_ARCH_SPARC            1\n#            define ACC_INFO_ARCH             \"sparc\"\n#        elif defined(__SPU__)\n#            define ACC_ARCH_SPU              1\n#            define ACC_INFO_ARCH             \"spu\"\n#        elif (UINT_MAX == ACC_0xffffL) && defined(__z80)\n#            define ACC_ARCH_Z80              1\n#            define ACC_INFO_ARCH             \"z80\"\n#        elif (ACC_ARCH_CRAY_PVP)\n#            if defined(_CRAYSV1)\n#                define ACC_ARCH_CRAY_SV1       1\n#                define ACC_INFO_ARCH           \"cray_sv1\"\n#            elif (_ADDR64)\n#                define ACC_ARCH_CRAY_T90       1\n#                define ACC_INFO_ARCH           \"cray_t90\"\n#            elif (_ADDR32)\n#                define ACC_ARCH_CRAY_YMP       1\n#                define ACC_INFO_ARCH           \"cray_ymp\"\n#            else\n#                define ACC_ARCH_CRAY_XMP       1\n#                define ACC_INFO_ARCH           \"cray_xmp\"\n#            endif\n#        else\n#            define ACC_ARCH_UNKNOWN          1\n#            define ACC_INFO_ARCH             \"unknown\"\n#        endif\n#    endif\n#    if 1 && (ACC_ARCH_UNKNOWN) && (ACC_OS_DOS32 || ACC_OS_OS2)\n#        error \"FIXME - missing define for CPU architecture\"\n#    endif\n#    if 1 && (ACC_ARCH_UNKNOWN) && (ACC_OS_WIN32)\n#        error \"FIXME - missing WIN32 define for CPU architecture\"\n#    endif\n#    if 1 && (ACC_ARCH_UNKNOWN) && (ACC_OS_WIN64)\n#        error \"FIXME - missing WIN64 define for CPU architecture\"\n#    endif\n#    if (ACC_OS_OS216 || ACC_OS_WIN16)\n#        define ACC_ARCH_I086PM           1\n#        define ACC_ARCH_IA16PM           1\n#    elif 1 && (ACC_OS_DOS16 && defined(BLX286))\n#        define ACC_ARCH_I086PM           1\n#        define ACC_ARCH_IA16PM           1\n#    elif 1 && (ACC_OS_DOS16 && defined(DOSX286))\n#        define ACC_ARCH_I086PM           1\n#        define ACC_ARCH_IA16PM           1\n#    elif 1 && (ACC_OS_DOS16 && ACC_CC_BORLANDC && defined(__DPMI16__))\n#        define ACC_ARCH_I086PM           1\n#        define ACC_ARCH_IA16PM           1\n#    endif\n#    if defined(ACC_ARCH_ARM_THUMB) && !defined(ACC_ARCH_ARM)\n#        error \"this should not happen\"\n#    endif\n#    if defined(ACC_ARCH_I086PM) && !defined(ACC_ARCH_I086)\n#        error \"this should not happen\"\n#    endif\n#    if (ACC_ARCH_I086)\n#        if (UINT_MAX != ACC_0xffffL)\n#            error \"this should not happen\"\n#        endif\n#        if (ULONG_MAX != ACC_0xffffffffL)\n#            error \"this should not happen\"\n#        endif\n#    endif\n#    if (ACC_ARCH_I386)\n#        if (UINT_MAX != ACC_0xffffL) && defined(__i386_int16__)\n#            error \"this should not happen\"\n#        endif\n#        if (UINT_MAX != ACC_0xffffffffL) && !defined(__i386_int16__)\n#            error \"this should not happen\"\n#        endif\n#        if (ULONG_MAX != ACC_0xffffffffL)\n#            error \"this should not happen\"\n#        endif\n#    endif\n#    if !defined(__ACC_MM_OVERRIDE)\n#        if (ACC_ARCH_I086)\n#            if (UINT_MAX != ACC_0xffffL)\n#                error \"this should not happen\"\n#            endif\n#            if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)\n#                define ACC_MM_TINY           1\n#            elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM)\n#                define ACC_MM_HUGE           1\n#            elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL)\n#                define ACC_MM_SMALL          1\n#            elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM)\n#                define ACC_MM_MEDIUM         1\n#            elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM)\n#                define ACC_MM_COMPACT        1\n#            elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL)\n#                define ACC_MM_LARGE          1\n#            elif (ACC_CC_AZTECC)\n#                if defined(_LARGE_CODE) && defined(_LARGE_DATA)\n#                    define ACC_MM_LARGE        1\n#                elif defined(_LARGE_CODE)\n#                    define ACC_MM_MEDIUM       1\n#                elif defined(_LARGE_DATA)\n#                    define ACC_MM_COMPACT      1\n#                else\n#                    define ACC_MM_SMALL        1\n#                endif\n#            elif (ACC_CC_ZORTECHC && defined(__VCM__))\n#                define ACC_MM_LARGE          1\n#            else\n#                error \"unknown memory model\"\n#            endif\n#            if (ACC_OS_DOS16 || ACC_OS_OS216 || ACC_OS_WIN16)\n#                define ACC_HAVE_MM_HUGE_PTR        1\n#                define ACC_HAVE_MM_HUGE_ARRAY      1\n#                if (ACC_MM_TINY)\n#                    undef ACC_HAVE_MM_HUGE_ARRAY\n#                endif\n#                if (ACC_CC_AZTECC || ACC_CC_PACIFICC || ACC_CC_ZORTECHC)\n#                    undef ACC_HAVE_MM_HUGE_PTR\n#                    undef ACC_HAVE_MM_HUGE_ARRAY\n#                elif (ACC_CC_DMC || ACC_CC_SYMANTECC)\n#                    undef ACC_HAVE_MM_HUGE_ARRAY\n#                elif (ACC_CC_MSC && defined(_QC))\n#                    undef ACC_HAVE_MM_HUGE_ARRAY\n#                    if (_MSC_VER < 600)\n#                        undef ACC_HAVE_MM_HUGE_PTR\n#                    endif\n#                elif (ACC_CC_TURBOC && (__TURBOC__ < 0x0295))\n#                    undef ACC_HAVE_MM_HUGE_ARRAY\n#                endif\n#                if (ACC_ARCH_I086PM) && !defined(ACC_HAVE_MM_HUGE_PTR)\n#                    if (ACC_OS_DOS16)\n#                        error \"this should not happen\"\n#                    elif (ACC_CC_ZORTECHC)\n#                    else\n#                        error \"this should not happen\"\n#                    endif\n#                endif\n#                ifdef __cplusplus\nextern \"C\" {\n#                endif\n#                if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0200))\n\textern void __near __cdecl _AHSHIFT(void);\n#                    define ACC_MM_AHSHIFT      ((unsigned) _AHSHIFT)\n#                elif (ACC_CC_DMC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)\n\textern void __near __cdecl _AHSHIFT(void);\n#                    define ACC_MM_AHSHIFT      ((unsigned) _AHSHIFT)\n#                elif (ACC_CC_MSC || ACC_CC_TOPSPEEDC)\n\textern void __near __cdecl _AHSHIFT(void);\n#                    define ACC_MM_AHSHIFT      ((unsigned) _AHSHIFT)\n#                elif (ACC_CC_TURBOC && (__TURBOC__ >= 0x0295))\n\textern void __near __cdecl _AHSHIFT(void);\n#                    define ACC_MM_AHSHIFT      ((unsigned) _AHSHIFT)\n#                elif ((ACC_CC_AZTECC || ACC_CC_PACIFICC || ACC_CC_TURBOC) && ACC_OS_DOS16)\n#                    define ACC_MM_AHSHIFT      12\n#                elif (ACC_CC_WATCOMC)\n\textern unsigned char _HShift;\n#                    define ACC_MM_AHSHIFT      ((unsigned) _HShift)\n#                else\n#                    error \"FIXME - implement ACC_MM_AHSHIFT\"\n#                endif\n#                ifdef __cplusplus\n}\n#                endif\n#            endif\n#        elif (ACC_ARCH_C166)\n#            if !defined(__MODEL__)\n#                error \"FIXME - C166 __MODEL__\"\n#            elif ((__MODEL__) == 0)\n#                define ACC_MM_SMALL          1\n#            elif ((__MODEL__) == 1)\n#                define ACC_MM_SMALL          1\n#            elif ((__MODEL__) == 2)\n#                define ACC_MM_LARGE          1\n#            elif ((__MODEL__) == 3)\n#                define ACC_MM_TINY           1\n#            elif ((__MODEL__) == 4)\n#                define ACC_MM_XTINY          1\n#            elif ((__MODEL__) == 5)\n#                define ACC_MM_XSMALL         1\n#            else\n#                error \"FIXME - C166 __MODEL__\"\n#            endif\n#        elif (ACC_ARCH_MCS251)\n#            if !defined(__MODEL__)\n#                error \"FIXME - MCS251 __MODEL__\"\n#            elif ((__MODEL__) == 0)\n#                define ACC_MM_SMALL          1\n#            elif ((__MODEL__) == 2)\n#                define ACC_MM_LARGE          1\n#            elif ((__MODEL__) == 3)\n#                define ACC_MM_TINY           1\n#            elif ((__MODEL__) == 4)\n#                define ACC_MM_XTINY          1\n#            elif ((__MODEL__) == 5)\n#                define ACC_MM_XSMALL         1\n#            else\n#                error \"FIXME - MCS251 __MODEL__\"\n#            endif\n#        elif (ACC_ARCH_MCS51)\n#            if !defined(__MODEL__)\n#                error \"FIXME - MCS51 __MODEL__\"\n#            elif ((__MODEL__) == 1)\n#                define ACC_MM_SMALL          1\n#            elif ((__MODEL__) == 2)\n#                define ACC_MM_LARGE          1\n#            elif ((__MODEL__) == 3)\n#                define ACC_MM_TINY           1\n#            elif ((__MODEL__) == 4)\n#                define ACC_MM_XTINY          1\n#            elif ((__MODEL__) == 5)\n#                define ACC_MM_XSMALL         1\n#            else\n#                error \"FIXME - MCS51 __MODEL__\"\n#            endif\n#        elif (ACC_ARCH_CRAY_PVP)\n#            define ACC_MM_PVP            1\n#        else\n#            define ACC_MM_FLAT           1\n#        endif\n#        if (ACC_MM_COMPACT)\n#            define ACC_INFO_MM           \"compact\"\n#        elif (ACC_MM_FLAT)\n#            define ACC_INFO_MM           \"flat\"\n#        elif (ACC_MM_HUGE)\n#            define ACC_INFO_MM           \"huge\"\n#        elif (ACC_MM_LARGE)\n#            define ACC_INFO_MM           \"large\"\n#        elif (ACC_MM_MEDIUM)\n#            define ACC_INFO_MM           \"medium\"\n#        elif (ACC_MM_PVP)\n#            define ACC_INFO_MM           \"pvp\"\n#        elif (ACC_MM_SMALL)\n#            define ACC_INFO_MM           \"small\"\n#        elif (ACC_MM_TINY)\n#            define ACC_INFO_MM           \"tiny\"\n#        else\n#            error \"unknown memory model\"\n#        endif\n#    endif\n#    if defined(SIZEOF_SHORT)\n#        define ACC_SIZEOF_SHORT          (SIZEOF_SHORT)\n#    endif\n#    if defined(SIZEOF_INT)\n#        define ACC_SIZEOF_INT            (SIZEOF_INT)\n#    endif\n#    if defined(SIZEOF_LONG)\n#        define ACC_SIZEOF_LONG           (SIZEOF_LONG)\n#    endif\n#    if defined(SIZEOF_LONG_LONG)\n#        define ACC_SIZEOF_LONG_LONG      (SIZEOF_LONG_LONG)\n#    endif\n#    if defined(SIZEOF___INT16)\n#        define ACC_SIZEOF___INT16        (SIZEOF___INT16)\n#    endif\n#    if defined(SIZEOF___INT32)\n#        define ACC_SIZEOF___INT32        (SIZEOF___INT32)\n#    endif\n#    if defined(SIZEOF___INT64)\n#        define ACC_SIZEOF___INT64        (SIZEOF___INT64)\n#    endif\n#    if defined(SIZEOF_VOID_P)\n#        define ACC_SIZEOF_VOID_P         (SIZEOF_VOID_P)\n#    endif\n#    if defined(SIZEOF_SIZE_T)\n#        define ACC_SIZEOF_SIZE_T         (SIZEOF_SIZE_T)\n#    endif\n#    if defined(SIZEOF_PTRDIFF_T)\n#        define ACC_SIZEOF_PTRDIFF_T      (SIZEOF_PTRDIFF_T)\n#    endif\n#    define __ACC_LSR(x,b)    (((x)+0ul) >> (b))\n#    if !defined(ACC_SIZEOF_SHORT)\n#        if (ACC_ARCH_CRAY_PVP)\n#            define ACC_SIZEOF_SHORT        8\n#        elif (USHRT_MAX == ACC_0xffffL)\n#            define ACC_SIZEOF_SHORT        2\n#        elif (__ACC_LSR(USHRT_MAX,7) == 1)\n#            define ACC_SIZEOF_SHORT        1\n#        elif (__ACC_LSR(USHRT_MAX,15) == 1)\n#            define ACC_SIZEOF_SHORT        2\n#        elif (__ACC_LSR(USHRT_MAX,31) == 1)\n#            define ACC_SIZEOF_SHORT        4\n#        elif (__ACC_LSR(USHRT_MAX,63) == 1)\n#            define ACC_SIZEOF_SHORT        8\n#        elif (__ACC_LSR(USHRT_MAX,127) == 1)\n#            define ACC_SIZEOF_SHORT        16\n#        else\n#            error \"ACC_SIZEOF_SHORT\"\n#        endif\n#    endif\n#    if !defined(ACC_SIZEOF_INT)\n#        if (ACC_ARCH_CRAY_PVP)\n#            define ACC_SIZEOF_INT          8\n#        elif (UINT_MAX == ACC_0xffffL)\n#            define ACC_SIZEOF_INT          2\n#        elif (UINT_MAX == ACC_0xffffffffL)\n#            define ACC_SIZEOF_INT          4\n#        elif (__ACC_LSR(UINT_MAX,7) == 1)\n#            define ACC_SIZEOF_INT          1\n#        elif (__ACC_LSR(UINT_MAX,15) == 1)\n#            define ACC_SIZEOF_INT          2\n#        elif (__ACC_LSR(UINT_MAX,31) == 1)\n#            define ACC_SIZEOF_INT          4\n#        elif (__ACC_LSR(UINT_MAX,63) == 1)\n#            define ACC_SIZEOF_INT          8\n#        elif (__ACC_LSR(UINT_MAX,127) == 1)\n#            define ACC_SIZEOF_INT          16\n#        else\n#            error \"ACC_SIZEOF_INT\"\n#        endif\n#    endif\n#    if !defined(ACC_SIZEOF_LONG)\n#        if (ULONG_MAX == ACC_0xffffffffL)\n#            define ACC_SIZEOF_LONG         4\n#        elif (__ACC_LSR(ULONG_MAX,7) == 1)\n#            define ACC_SIZEOF_LONG         1\n#        elif (__ACC_LSR(ULONG_MAX,15) == 1)\n#            define ACC_SIZEOF_LONG         2\n#        elif (__ACC_LSR(ULONG_MAX,31) == 1)\n#            define ACC_SIZEOF_LONG         4\n#        elif (__ACC_LSR(ULONG_MAX,63) == 1)\n#            define ACC_SIZEOF_LONG         8\n#        elif (__ACC_LSR(ULONG_MAX,127) == 1)\n#            define ACC_SIZEOF_LONG         16\n#        else\n#            error \"ACC_SIZEOF_LONG\"\n#        endif\n#    endif\n#    if !defined(ACC_SIZEOF_LONG_LONG) && !defined(ACC_SIZEOF___INT64)\n#        if (ACC_SIZEOF_LONG > 0 && ACC_SIZEOF_LONG < 8)\n#            if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)\n#                if (ACC_CC_GNUC >= 0x030300ul)\n#                    if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)\n#                        define ACC_SIZEOF_LONG_LONG      ACC_SIZEOF_LONG\n#                    elif (__ACC_LSR(__LONG_LONG_MAX__,30) == 1)\n#                        define ACC_SIZEOF_LONG_LONG      4\n#                    endif\n#                endif\n#            endif\n#        endif\n#    endif\n#    if !defined(ACC_SIZEOF_LONG_LONG) && !defined(ACC_SIZEOF___INT64)\n#        if (ACC_SIZEOF_LONG > 0 && ACC_SIZEOF_LONG < 8)\n#            if (ACC_ARCH_I086 && ACC_CC_DMC)\n#            elif (ACC_CC_CILLY) && defined(__GNUC__)\n#                define ACC_SIZEOF_LONG_LONG      8\n#            elif (ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#                define ACC_SIZEOF_LONG_LONG      8\n#            elif ((ACC_OS_WIN32 || ACC_OS_WIN64 || defined(_WIN32)) && ACC_CC_MSC && (_MSC_VER >= 1400))\n#                define ACC_SIZEOF_LONG_LONG      8\n#            elif (ACC_OS_WIN64 || defined(_WIN64))\n#                define ACC_SIZEOF___INT64        8\n#            elif (ACC_ARCH_I386 && (ACC_CC_DMC))\n#                define ACC_SIZEOF_LONG_LONG      8\n#            elif (ACC_ARCH_I386 && (ACC_CC_SYMANTECC && (__SC__ >= 0x700)))\n#                define ACC_SIZEOF_LONG_LONG      8\n#            elif (ACC_ARCH_I386 && (ACC_CC_INTELC && defined(__linux__)))\n#                define ACC_SIZEOF_LONG_LONG      8\n#            elif (ACC_ARCH_I386 && (ACC_CC_MWERKS || ACC_CC_PELLESC || ACC_CC_PGI || ACC_CC_SUNPROC))\n#                define ACC_SIZEOF_LONG_LONG      8\n#            elif (ACC_ARCH_I386 && (ACC_CC_INTELC || ACC_CC_MSC))\n#                define ACC_SIZEOF___INT64        8\n#            elif ((ACC_OS_WIN32 || defined(_WIN32)) && (ACC_CC_MSC))\n#                define ACC_SIZEOF___INT64        8\n#            elif (ACC_ARCH_I386 && (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0520)))\n#                define ACC_SIZEOF___INT64        8\n#            elif (ACC_ARCH_I386 && (ACC_CC_WATCOMC && (__WATCOMC__ >= 1100)))\n#                define ACC_SIZEOF___INT64        8\n#            elif (ACC_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))\n#                define ACC_SIZEOF___INT64        8\n#            elif (ACC_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)\n#                define ACC_SIZEOF_LONG_LONG      8\n#            elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)\n#                define ACC_SIZEOF_LONG_LONG      8\n#            elif (ACC_CC_SDCC) && (ACC_SIZEOF_INT == 2)\n#            elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)\n#                define ACC_SIZEOF_LONG_LONG      8\n#            endif\n#        endif\n#    endif\n#    if defined(__cplusplus) && defined(ACC_CC_GNUC)\n#        if (ACC_CC_GNUC < 0x020800ul)\n#            undef ACC_SIZEOF_LONG_LONG\n#        endif\n#    endif\n#    if defined(ACC_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)\n#        undef ACC_SIZEOF_LONG_LONG\n#    endif\n#    if !defined(ACC_SIZEOF_VOID_P)\n#        if (ACC_ARCH_I086)\n#            define __ACC_WORDSIZE            2\n#            if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)\n#                define ACC_SIZEOF_VOID_P       2\n#            elif (ACC_MM_COMPACT || ACC_MM_LARGE || ACC_MM_HUGE)\n#                define ACC_SIZEOF_VOID_P       4\n#            else\n#                error \"ACC_MM\"\n#            endif\n#        elif (ACC_ARCH_AVR || ACC_ARCH_Z80)\n#            define __ACC_WORDSIZE            1\n#            define ACC_SIZEOF_VOID_P         2\n#        elif (ACC_ARCH_C166 || ACC_ARCH_MCS51 || ACC_ARCH_MCS251 || ACC_ARCH_MSP430)\n#            define ACC_SIZEOF_VOID_P         2\n#        elif (ACC_ARCH_H8300)\n#            if defined(__NORMAL_MODE__)\n#                define __ACC_WORDSIZE          4\n#                define ACC_SIZEOF_VOID_P       2\n#            elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)\n#                define __ACC_WORDSIZE          4\n#                define ACC_SIZEOF_VOID_P       4\n#            else\n#                define __ACC_WORDSIZE          2\n#                define ACC_SIZEOF_VOID_P       2\n#            endif\n#            if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x040000ul)) && (ACC_SIZEOF_INT == 4)\n#                define ACC_SIZEOF_SIZE_T       ACC_SIZEOF_INT\n#                define ACC_SIZEOF_PTRDIFF_T    ACC_SIZEOF_INT\n#            endif\n#        elif (ACC_ARCH_M16C)\n#            define __ACC_WORDSIZE            2\n#            if defined(__m32c_cpu__) || defined(__m32cm_cpu__)\n#                define ACC_SIZEOF_VOID_P       4\n#            else\n#                define ACC_SIZEOF_VOID_P       2\n#            endif\n#        elif (ACC_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))\n#            define __ACC_WORDSIZE            8\n#            define ACC_SIZEOF_VOID_P         4\n#        elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)\n#            define __ACC_WORDSIZE            8\n#            define ACC_SIZEOF_VOID_P         8\n#        elif (ACC_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)\n#            define ACC_SIZEOF_VOID_P         ACC_SIZEOF_LONG\n#            define ACC_SIZEOF_SIZE_T         ACC_SIZEOF_LONG\n#            define ACC_SIZEOF_PTRDIFF_T      ACC_SIZEOF_LONG\n#        elif (ACC_OS_OS400 || defined(__OS400__))\n#            define __ACC_WORDSIZE            ACC_SIZEOF_LONG\n#            define ACC_SIZEOF_VOID_P         16\n#            define ACC_SIZEOF_SIZE_T         ACC_SIZEOF_LONG\n#            define ACC_SIZEOF_PTRDIFF_T      ACC_SIZEOF_LONG\n#        elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)\n#            define ACC_SIZEOF_VOID_P         8\n#            define ACC_SIZEOF_SIZE_T         ACC_SIZEOF_LONG\n#            define ACC_SIZEOF_PTRDIFF_T      ACC_SIZEOF_LONG\n#        elif (ACC_ARCH_SPU)\n#            if 0\n#                define __ACC_WORDSIZE            16\n#            endif\n#            define ACC_SIZEOF_VOID_P         4\n#        else\n#            define ACC_SIZEOF_VOID_P         ACC_SIZEOF_LONG\n#        endif\n#    endif\n#    if !defined(ACC_WORDSIZE)\n#        if defined(__ACC_WORDSIZE)\n#            define ACC_WORDSIZE            __ACC_WORDSIZE\n#        else\n#            define ACC_WORDSIZE            ACC_SIZEOF_VOID_P\n#        endif\n#    endif\n#    if !defined(ACC_SIZEOF_SIZE_T)\n#        if (ACC_ARCH_I086 || ACC_ARCH_M16C)\n#            define ACC_SIZEOF_SIZE_T         2\n#        else\n#            define ACC_SIZEOF_SIZE_T         ACC_SIZEOF_VOID_P\n#        endif\n#    endif\n#    if !defined(ACC_SIZEOF_PTRDIFF_T)\n#        if (ACC_ARCH_I086)\n#            if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM || ACC_MM_HUGE)\n#                define ACC_SIZEOF_PTRDIFF_T    ACC_SIZEOF_VOID_P\n#            elif (ACC_MM_COMPACT || ACC_MM_LARGE)\n#                if (ACC_CC_BORLANDC || ACC_CC_TURBOC)\n#                    define ACC_SIZEOF_PTRDIFF_T  4\n#                else\n#                    define ACC_SIZEOF_PTRDIFF_T  2\n#                endif\n#            else\n#                error \"ACC_MM\"\n#            endif\n#        else\n#            define ACC_SIZEOF_PTRDIFF_T      ACC_SIZEOF_SIZE_T\n#        endif\n#    endif\n#    if defined(ACC_ABI_NEUTRAL_ENDIAN)\n#        undef ACC_ABI_BIG_ENDIAN\n#        undef ACC_ABI_LITTLE_ENDIAN\n#    elif !defined(ACC_ABI_BIG_ENDIAN) && !defined(ACC_ABI_LITTLE_ENDIAN)\n#        if (ACC_ARCH_ALPHA) && (ACC_ARCH_CRAY_MPP)\n#            define ACC_ABI_BIG_ENDIAN        1\n#        elif (ACC_ARCH_ALPHA || ACC_ARCH_AMD64 || ACC_ARCH_BLACKFIN || ACC_ARCH_CRIS || ACC_ARCH_I086 || ACC_ARCH_I386 || ACC_ARCH_MSP430)\n#            define ACC_ABI_LITTLE_ENDIAN     1\n#        elif (ACC_ARCH_M68K || ACC_ARCH_S390)\n#            define ACC_ABI_BIG_ENDIAN        1\n#        elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)\n#            if (__LITTLE_ENDIAN__ == 1)\n#                define ACC_ABI_LITTLE_ENDIAN   1\n#            else\n#                define ACC_ABI_BIG_ENDIAN      1\n#            endif\n#        elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)\n#            define ACC_ABI_BIG_ENDIAN        1\n#        elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)\n#            define ACC_ABI_LITTLE_ENDIAN     1\n#        elif 1 && (ACC_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__)\n#            define ACC_ABI_BIG_ENDIAN        1\n#        elif 1 && (ACC_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)\n#            define ACC_ABI_LITTLE_ENDIAN     1\n#        elif 1 && (ACC_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)\n#            define ACC_ABI_BIG_ENDIAN        1\n#        elif 1 && (ACC_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)\n#            define ACC_ABI_LITTLE_ENDIAN     1\n#        endif\n#    endif\n#    if defined(ACC_ABI_BIG_ENDIAN) && defined(ACC_ABI_LITTLE_ENDIAN)\n#        error \"this should not happen\"\n#    endif\n#    if defined(ACC_ABI_BIG_ENDIAN)\n#        define ACC_INFO_ABI_ENDIAN       \"be\"\n#    elif defined(ACC_ABI_LITTLE_ENDIAN)\n#        define ACC_INFO_ABI_ENDIAN       \"le\"\n#    elif defined(ACC_ABI_NEUTRAL_ENDIAN)\n#        define ACC_INFO_ABI_ENDIAN       \"neutral\"\n#    endif\n#    if (ACC_SIZEOF_INT == 1 && ACC_SIZEOF_LONG == 2 && ACC_SIZEOF_VOID_P == 2)\n#        define ACC_ABI_I8LP16         1\n#        define ACC_INFO_ABI_PM       \"i8lp16\"\n#    elif (ACC_SIZEOF_INT == 2 && ACC_SIZEOF_LONG == 2 && ACC_SIZEOF_VOID_P == 2)\n#        define ACC_ABI_ILP16         1\n#        define ACC_INFO_ABI_PM       \"ilp16\"\n#    elif (ACC_SIZEOF_INT == 4 && ACC_SIZEOF_LONG == 4 && ACC_SIZEOF_VOID_P == 4)\n#        define ACC_ABI_ILP32         1\n#        define ACC_INFO_ABI_PM       \"ilp32\"\n#    elif (ACC_SIZEOF_INT == 4 && ACC_SIZEOF_LONG == 4 && ACC_SIZEOF_VOID_P == 8 && ACC_SIZEOF_SIZE_T == 8)\n#        define ACC_ABI_LLP64         1\n#        define ACC_INFO_ABI_PM       \"llp64\"\n#    elif (ACC_SIZEOF_INT == 4 && ACC_SIZEOF_LONG == 8 && ACC_SIZEOF_VOID_P == 8)\n#        define ACC_ABI_LP64          1\n#        define ACC_INFO_ABI_PM       \"lp64\"\n#    elif (ACC_SIZEOF_INT == 8 && ACC_SIZEOF_LONG == 8 && ACC_SIZEOF_VOID_P == 8)\n#        define ACC_ABI_ILP64         1\n#        define ACC_INFO_ABI_PM       \"ilp64\"\n#    elif (ACC_SIZEOF_INT == 4 && ACC_SIZEOF_LONG == 8 && ACC_SIZEOF_VOID_P == 4)\n#        define ACC_ABI_IP32L64       1\n#        define ACC_INFO_ABI_PM       \"ip32l64\"\n#    endif\n#    if !defined(__ACC_LIBC_OVERRIDE)\n#        if defined(ACC_LIBC_NAKED)\n#            define ACC_INFO_LIBC         \"naked\"\n#        elif defined(ACC_LIBC_FREESTANDING)\n#            define ACC_INFO_LIBC         \"freestanding\"\n#        elif defined(ACC_LIBC_MOSTLY_FREESTANDING)\n#            define ACC_INFO_LIBC         \"mfreestanding\"\n#        elif defined(ACC_LIBC_ISOC90)\n#            define ACC_INFO_LIBC         \"isoc90\"\n#        elif defined(ACC_LIBC_ISOC99)\n#            define ACC_INFO_LIBC         \"isoc99\"\n#        elif defined(__dietlibc__)\n#            define ACC_LIBC_DIETLIBC     1\n#            define ACC_INFO_LIBC         \"dietlibc\"\n#        elif defined(_NEWLIB_VERSION)\n#            define ACC_LIBC_NEWLIB       1\n#            define ACC_INFO_LIBC         \"newlib\"\n#        elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)\n#            if defined(__UCLIBC_SUBLEVEL__)\n#                define ACC_LIBC_UCLIBC     (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)\n#            else\n#                define ACC_LIBC_UCLIBC     0x00090bL\n#            endif\n#            define ACC_INFO_LIBC         \"uclibc\"\n#        elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)\n#            define ACC_LIBC_GLIBC        (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)\n#            define ACC_INFO_LIBC         \"glibc\"\n#        elif (ACC_CC_MWERKS) && defined(__MSL__)\n#            define ACC_LIBC_MSL          __MSL__\n#            define ACC_INFO_LIBC         \"msl\"\n#        elif 1 && defined(__IAR_SYSTEMS_ICC__)\n#            define ACC_LIBC_ISOC90       1\n#            define ACC_INFO_LIBC         \"isoc90\"\n#        else\n#            define ACC_LIBC_DEFAULT      1\n#            define ACC_INFO_LIBC         \"default\"\n#        endif\n#    endif\n#    if !defined(__acc_gnuc_extension__)\n#        if (ACC_CC_GNUC >= 0x020800ul)\n#            define __acc_gnuc_extension__    __extension__\n#        elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#            define __acc_gnuc_extension__    __extension__\n#        else\n#            define __acc_gnuc_extension__\n#        endif\n#    endif\n#    if !defined(__acc_ua_volatile)\n#        define __acc_ua_volatile     volatile\n#    endif\n#    if !defined(__acc_alignof)\n#        if (ACC_CC_CILLY || ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE || ACC_CC_PGI)\n#            define __acc_alignof(e)      __alignof__(e)\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 700))\n#            define __acc_alignof(e)      __alignof__(e)\n#        elif (ACC_CC_MSC && (_MSC_VER >= 1300))\n#            define __acc_alignof(e)      __alignof(e)\n#        endif\n#    endif\n#    if defined(__acc_alignof)\n#        define __acc_HAVE_alignof 1\n#    endif\n#    if !defined(__acc_constructor)\n#        if (ACC_CC_GNUC >= 0x030400ul)\n#            define __acc_constructor     __attribute__((__constructor__,__used__))\n#        elif (ACC_CC_GNUC >= 0x020700ul)\n#            define __acc_constructor     __attribute__((__constructor__))\n#        elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#            define __acc_constructor     __attribute__((__constructor__))\n#        endif\n#    endif\n#    if defined(__acc_constructor)\n#        define __acc_HAVE_constructor 1\n#    endif\n#    if !defined(__acc_destructor)\n#        if (ACC_CC_GNUC >= 0x030400ul)\n#            define __acc_destructor      __attribute__((__destructor__,__used__))\n#        elif (ACC_CC_GNUC >= 0x020700ul)\n#            define __acc_destructor      __attribute__((__destructor__))\n#        elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#            define __acc_destructor      __attribute__((__destructor__))\n#        endif\n#    endif\n#    if defined(__acc_destructor)\n#        define __acc_HAVE_destructor 1\n#    endif\n#    if defined(__acc_HAVE_destructor) && !defined(__acc_HAVE_constructor)\n#        error \"this should not happen\"\n#    endif\n#    if !defined(__acc_inline)\n#        if (ACC_CC_TURBOC && (__TURBOC__ <= 0x0295))\n#        elif defined(__cplusplus)\n#            define __acc_inline          inline\n#        elif (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0550))\n#            define __acc_inline          __inline\n#        elif (ACC_CC_CILLY || ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE || ACC_CC_PGI)\n#            define __acc_inline          __inline__\n#        elif (ACC_CC_DMC)\n#            define __acc_inline          __inline\n#        elif (ACC_CC_INTELC)\n#            define __acc_inline          __inline\n#        elif (ACC_CC_MWERKS && (__MWERKS__ >= 0x2405))\n#            define __acc_inline          __inline\n#        elif (ACC_CC_MSC && (_MSC_VER >= 900))\n#            define __acc_inline          __inline\n#        elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)\n#            define __acc_inline          inline\n#        endif\n#    endif\n#    if defined(__acc_inline)\n#        define __acc_HAVE_inline 1\n#    else\n#        define __acc_inline\n#    endif\n#    if !defined(__acc_forceinline)\n#        if (ACC_CC_GNUC >= 0x030200ul)\n#            define __acc_forceinline     __inline__ __attribute__((__always_inline__))\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 450) && ACC_CC_SYNTAX_MSC)\n#            define __acc_forceinline     __forceinline\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 800) && ACC_CC_SYNTAX_GNUC)\n#            define __acc_forceinline     __inline__ __attribute__((__always_inline__))\n#        elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#            define __acc_forceinline     __inline__ __attribute__((__always_inline__))\n#        elif (ACC_CC_MSC && (_MSC_VER >= 1200))\n#            define __acc_forceinline     __forceinline\n#        endif\n#    endif\n#    if defined(__acc_forceinline)\n#        define __acc_HAVE_forceinline 1\n#    else\n#        define __acc_forceinline\n#    endif\n#    if !defined(__acc_noinline)\n#        if 1 && (ACC_ARCH_I386) && (ACC_CC_GNUC >= 0x040000ul) && (ACC_CC_GNUC < 0x040003ul)\n#            define __acc_noinline        __attribute__((__noinline__,__used__))\n#        elif (ACC_CC_GNUC >= 0x030200ul)\n#            define __acc_noinline        __attribute__((__noinline__))\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 600) && ACC_CC_SYNTAX_MSC)\n#            define __acc_noinline        __declspec(noinline)\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 800) && ACC_CC_SYNTAX_GNUC)\n#            define __acc_noinline        __attribute__((__noinline__))\n#        elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#            define __acc_noinline        __attribute__((__noinline__))\n#        elif (ACC_CC_MSC && (_MSC_VER >= 1300))\n#            define __acc_noinline        __declspec(noinline)\n#        elif (ACC_CC_MWERKS && (__MWERKS__ >= 0x3200) && (ACC_OS_WIN32 || ACC_OS_WIN64))\n#            if defined(__cplusplus)\n#            else\n#                define __acc_noinline      __declspec(noinline)\n#            endif\n#        endif\n#    endif\n#    if defined(__acc_noinline)\n#        define __acc_HAVE_noinline 1\n#    else\n#        define __acc_noinline\n#    endif\n#    if (defined(__acc_HAVE_forceinline) || defined(__acc_HAVE_noinline)) && !defined(__acc_HAVE_inline)\n#        error \"this should not happen\"\n#    endif\n#    if !defined(__acc_noreturn)\n#        if (ACC_CC_GNUC >= 0x020700ul)\n#            define __acc_noreturn        __attribute__((__noreturn__))\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 450) && ACC_CC_SYNTAX_MSC)\n#            define __acc_noreturn        __declspec(noreturn)\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 600) && ACC_CC_SYNTAX_GNUC)\n#            define __acc_noreturn        __attribute__((__noreturn__))\n#        elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#            define __acc_noreturn        __attribute__((__noreturn__))\n#        elif (ACC_CC_MSC && (_MSC_VER >= 1200))\n#            define __acc_noreturn        __declspec(noreturn)\n#        endif\n#    endif\n#    if defined(__acc_noreturn)\n#        define __acc_HAVE_noreturn 1\n#    else\n#        define __acc_noreturn\n#    endif\n#    if !defined(__acc_nothrow)\n#        if (ACC_CC_GNUC >= 0x030300ul)\n#            define __acc_nothrow         __attribute__((__nothrow__))\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 450) && ACC_CC_SYNTAX_MSC) && defined(__cplusplus)\n#            define __acc_nothrow         __declspec(nothrow)\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 800) && ACC_CC_SYNTAX_GNUC)\n#            define __acc_nothrow         __attribute__((__nothrow__))\n#        elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#            define __acc_nothrow         __attribute__((__nothrow__))\n#        elif (ACC_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)\n#            define __acc_nothrow         __declspec(nothrow)\n#        endif\n#    endif\n#    if defined(__acc_nothrow)\n#        define __acc_HAVE_nothrow 1\n#    else\n#        define __acc_nothrow\n#    endif\n#    if !defined(__acc_restrict)\n#        if (ACC_CC_GNUC >= 0x030400ul)\n#            define __acc_restrict        __restrict__\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 600) && ACC_CC_SYNTAX_GNUC)\n#            define __acc_restrict        __restrict__\n#        elif (ACC_CC_LLVM)\n#            define __acc_restrict        __restrict__\n#        elif (ACC_CC_MSC && (_MSC_VER >= 1400))\n#            define __acc_restrict        __restrict\n#        endif\n#    endif\n#    if defined(__acc_restrict)\n#        define __acc_HAVE_restrict 1\n#    else\n#        define __acc_restrict\n#    endif\n#    if !defined(__acc_likely) && !defined(__acc_unlikely)\n#        if (ACC_CC_GNUC >= 0x030200ul)\n#            define __acc_likely(e)       (__builtin_expect(!!(e),1))\n#            define __acc_unlikely(e)     (__builtin_expect(!!(e),0))\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER >= 800))\n#            define __acc_likely(e)       (__builtin_expect(!!(e),1))\n#            define __acc_unlikely(e)     (__builtin_expect(!!(e),0))\n#        elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#            define __acc_likely(e)       (__builtin_expect(!!(e),1))\n#            define __acc_unlikely(e)     (__builtin_expect(!!(e),0))\n#        endif\n#    endif\n#    if defined(__acc_likely)\n#        define __acc_HAVE_likely 1\n#    else\n#        define __acc_likely(e)       (e)\n#    endif\n#    if defined(__acc_unlikely)\n#        define __acc_HAVE_unlikely 1\n#    else\n#        define __acc_unlikely(e)     (e)\n#    endif\n#    if !defined(ACC_UNUSED)\n#        if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0600))\n#            define ACC_UNUSED(var)         ((void) &var)\n#        elif (ACC_CC_BORLANDC || ACC_CC_HIGHC || ACC_CC_NDPC || ACC_CC_PELLESC || ACC_CC_TURBOC)\n#            define ACC_UNUSED(var)         if (&var) ; else\n#        elif (ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#            define ACC_UNUSED(var)         ((void) var)\n#        elif (ACC_CC_MSC && (_MSC_VER < 900))\n#            define ACC_UNUSED(var)         if (&var) ; else\n#        elif (ACC_CC_KEILC)\n#            define ACC_UNUSED(var)         {extern int __acc_unused[1-2*!(sizeof(var)>0)];}\n#        elif (ACC_CC_PACIFICC)\n#            define ACC_UNUSED(var)         ((void) sizeof(var))\n#        elif (ACC_CC_WATCOMC) && defined(__cplusplus)\n#            define ACC_UNUSED(var)         ((void) var)\n#        else\n#            define ACC_UNUSED(var)         ((void) &var)\n#        endif\n#    endif\n#    if !defined(ACC_UNUSED_FUNC)\n#        if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0600))\n#            define ACC_UNUSED_FUNC(func)   ((void) func)\n#        elif (ACC_CC_BORLANDC || ACC_CC_NDPC || ACC_CC_TURBOC)\n#            define ACC_UNUSED_FUNC(func)   if (func) ; else\n#        elif (ACC_CC_LLVM)\n#            define ACC_UNUSED_FUNC(func)   ((void) &func)\n#        elif (ACC_CC_MSC && (_MSC_VER < 900))\n#            define ACC_UNUSED_FUNC(func)   if (func) ; else\n#        elif (ACC_CC_MSC)\n#            define ACC_UNUSED_FUNC(func)   ((void) &func)\n#        elif (ACC_CC_KEILC || ACC_CC_PELLESC)\n#            define ACC_UNUSED_FUNC(func)   {extern int __acc_unused[1-2*!(sizeof((int)func)>0)];}\n#        else\n#            define ACC_UNUSED_FUNC(func)   ((void) func)\n#        endif\n#    endif\n#    if !defined(ACC_UNUSED_LABEL)\n#        if (ACC_CC_WATCOMC) && defined(__cplusplus)\n#            define ACC_UNUSED_LABEL(l)     switch(0) case 1:goto l\n#        elif (ACC_CC_INTELC || ACC_CC_WATCOMC)\n#            define ACC_UNUSED_LABEL(l)     if (0) goto l\n#        else\n#            define ACC_UNUSED_LABEL(l)     switch(0) case 1:goto l\n#        endif\n#    endif\n#    if !defined(ACC_DEFINE_UNINITIALIZED_VAR)\n#        if 0\n#            define ACC_DEFINE_UNINITIALIZED_VAR(type,var,init)  type var\n#        elif 0 && (ACC_CC_GNUC)\n#            define ACC_DEFINE_UNINITIALIZED_VAR(type,var,init)  type var = var\n#        else\n#            define ACC_DEFINE_UNINITIALIZED_VAR(type,var,init)  type var = init\n#        endif\n#    endif\n#    if !defined(ACC_COMPILE_TIME_ASSERT_HEADER)\n#        if (ACC_CC_AZTECC || ACC_CC_ZORTECHC)\n#            define ACC_COMPILE_TIME_ASSERT_HEADER(e)  extern int __acc_cta[1-!(e)];\n#        elif (ACC_CC_DMC || ACC_CC_SYMANTECC)\n#            define ACC_COMPILE_TIME_ASSERT_HEADER(e)  extern int __acc_cta[1u-2*!(e)];\n#        elif (ACC_CC_TURBOC && (__TURBOC__ == 0x0295))\n#            define ACC_COMPILE_TIME_ASSERT_HEADER(e)  extern int __acc_cta[1-!(e)];\n#        else\n#            define ACC_COMPILE_TIME_ASSERT_HEADER(e)  extern int __acc_cta[1-2*!(e)];\n#        endif\n#    endif\n#    if !defined(ACC_COMPILE_TIME_ASSERT)\n#        if (ACC_CC_AZTECC)\n#            define ACC_COMPILE_TIME_ASSERT(e)  {typedef int __acc_cta_t[1-!(e)];}\n#        elif (ACC_CC_DMC || ACC_CC_PACIFICC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)\n#            define ACC_COMPILE_TIME_ASSERT(e)  switch(0) case 1:case !(e):break;\n#        elif (ACC_CC_MSC && (_MSC_VER < 900))\n#            define ACC_COMPILE_TIME_ASSERT(e)  switch(0) case 1:case !(e):break;\n#        elif (ACC_CC_TURBOC && (__TURBOC__ == 0x0295))\n#            define ACC_COMPILE_TIME_ASSERT(e)  switch(0) case 1:case !(e):break;\n#        else\n#            define ACC_COMPILE_TIME_ASSERT(e)  {typedef int __acc_cta_t[1-2*!(e)];}\n#        endif\n#    endif\n#    if (ACC_ARCH_I086 || ACC_ARCH_I386) && (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)\n#        if (ACC_CC_GNUC || ACC_CC_HIGHC || ACC_CC_NDPC || ACC_CC_PACIFICC)\n#        elif (ACC_CC_DMC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)\n#            define __acc_cdecl                 __cdecl\n#            define __acc_cdecl_atexit\n#            define __acc_cdecl_main            __cdecl\n#            if (ACC_OS_OS2 && (ACC_CC_DMC || ACC_CC_SYMANTECC))\n#                define __acc_cdecl_qsort         __pascal\n#            elif (ACC_OS_OS2 && (ACC_CC_ZORTECHC))\n#                define __acc_cdecl_qsort         _stdcall\n#            else\n#                define __acc_cdecl_qsort         __cdecl\n#            endif\n#        elif (ACC_CC_WATCOMC)\n#            define __acc_cdecl                 __cdecl\n#        else\n#            define __acc_cdecl                 __cdecl\n#            define __acc_cdecl_atexit          __cdecl\n#            define __acc_cdecl_main            __cdecl\n#            define __acc_cdecl_qsort           __cdecl\n#        endif\n#        if (ACC_CC_GNUC || ACC_CC_HIGHC || ACC_CC_NDPC || ACC_CC_PACIFICC || ACC_CC_WATCOMC)\n#        elif (ACC_OS_OS2 && (ACC_CC_DMC || ACC_CC_SYMANTECC))\n#            define __acc_cdecl_sighandler      __pascal\n#        elif (ACC_OS_OS2 && (ACC_CC_ZORTECHC))\n#            define __acc_cdecl_sighandler      _stdcall\n#        elif (ACC_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)\n#            define __acc_cdecl_sighandler      __clrcall\n#        elif (ACC_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))\n#            if defined(_DLL)\n#                define __acc_cdecl_sighandler    _far _cdecl _loadds\n#            elif defined(_MT)\n#                define __acc_cdecl_sighandler    _far _cdecl\n#            else\n#                define __acc_cdecl_sighandler    _cdecl\n#            endif\n#        else\n#            define __acc_cdecl_sighandler      __cdecl\n#        endif\n#    elif (ACC_ARCH_I386) && (ACC_CC_WATCOMC)\n#        define __acc_cdecl                   __cdecl\n#    elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))\n#        define __acc_cdecl                   cdecl\n#    endif\n#    if !defined(__acc_cdecl)\n#        define __acc_cdecl\n#    endif\n#    if !defined(__acc_cdecl_atexit)\n#        define __acc_cdecl_atexit\n#    endif\n#    if !defined(__acc_cdecl_main)\n#        define __acc_cdecl_main\n#    endif\n#    if !defined(__acc_cdecl_qsort)\n#        define __acc_cdecl_qsort\n#    endif\n#    if !defined(__acc_cdecl_sighandler)\n#        define __acc_cdecl_sighandler\n#    endif\n#    if !defined(__acc_cdecl_va)\n#        define __acc_cdecl_va                __acc_cdecl\n#    endif\n#    if !defined(ACC_CFG_NO_WINDOWS_H)\n#        if (ACC_OS_CYGWIN || (ACC_OS_EMX && defined(__RSXNT__)) || ACC_OS_WIN32 || ACC_OS_WIN64)\n#            if (ACC_CC_WATCOMC && (__WATCOMC__ < 1000))\n#            elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)\n#            elif ((ACC_OS_CYGWIN || defined(__MINGW32__)) && (ACC_CC_GNUC && (ACC_CC_GNUC < 0x025f00ul)))\n#            else\n#                define ACC_HAVE_WINDOWS_H 1\n#            endif\n#        endif\n#    endif\n#    if (ACC_ARCH_ALPHA)\n#        define ACC_OPT_AVOID_UINT_INDEX  1\n#        define ACC_OPT_AVOID_SHORT       1\n#        define ACC_OPT_AVOID_USHORT      1\n#    elif (ACC_ARCH_AMD64)\n#        define ACC_OPT_AVOID_INT_INDEX   1\n#        define ACC_OPT_AVOID_UINT_INDEX  1\n#        define ACC_OPT_UNALIGNED16       1\n#        define ACC_OPT_UNALIGNED32       1\n#        define ACC_OPT_UNALIGNED64       1\n#    elif (ACC_ARCH_ARM && ACC_ARCH_ARM_THUMB)\n#    elif (ACC_ARCH_ARM)\n#        define ACC_OPT_AVOID_SHORT       1\n#        define ACC_OPT_AVOID_USHORT      1\n#    elif (ACC_ARCH_CRIS)\n#        define ACC_OPT_UNALIGNED16       1\n#        define ACC_OPT_UNALIGNED32       1\n#    elif (ACC_ARCH_I386)\n#        define ACC_OPT_UNALIGNED16       1\n#        define ACC_OPT_UNALIGNED32       1\n#    elif (ACC_ARCH_IA64)\n#        define ACC_OPT_AVOID_INT_INDEX   1\n#        define ACC_OPT_AVOID_UINT_INDEX  1\n#        define ACC_OPT_PREFER_POSTINC    1\n#    elif (ACC_ARCH_M68K)\n#        define ACC_OPT_PREFER_POSTINC    1\n#        define ACC_OPT_PREFER_PREDEC     1\n#        if defined(__mc68020__) && !defined(__mcoldfire__)\n#            define ACC_OPT_UNALIGNED16     1\n#            define ACC_OPT_UNALIGNED32     1\n#        endif\n#    elif (ACC_ARCH_MIPS)\n#        define ACC_OPT_AVOID_UINT_INDEX  1\n#    elif (ACC_ARCH_POWERPC)\n#        define ACC_OPT_PREFER_PREINC     1\n#        define ACC_OPT_PREFER_PREDEC     1\n#        if defined(ACC_ABI_BIG_ENDIAN)\n#            define ACC_OPT_UNALIGNED16     1\n#            define ACC_OPT_UNALIGNED32     1\n#        endif\n#    elif (ACC_ARCH_S390)\n#        define ACC_OPT_UNALIGNED16       1\n#        define ACC_OPT_UNALIGNED32       1\n#        if (ACC_SIZEOF_SIZE_T == 8)\n#            define ACC_OPT_UNALIGNED64     1\n#        endif\n#    elif (ACC_ARCH_SH)\n#        define ACC_OPT_PREFER_POSTINC    1\n#        define ACC_OPT_PREFER_PREDEC     1\n#    endif\n#    if !defined(ACC_CFG_NO_INLINE_ASM)\n#        if defined(ACC_CC_LLVM)\n#            define ACC_CFG_NO_INLINE_ASM 1\n#        endif\n#    endif\n#    if !defined(ACC_CFG_NO_UNALIGNED)\n#        if defined(ACC_ABI_NEUTRAL_ENDIAN) || defined(ACC_ARCH_GENERIC)\n#            define ACC_CFG_NO_UNALIGNED 1\n#        endif\n#    endif\n#    if defined(ACC_CFG_NO_UNALIGNED)\n#        undef ACC_OPT_UNALIGNED16\n#        undef ACC_OPT_UNALIGNED32\n#        undef ACC_OPT_UNALIGNED64\n#    endif\n#    if defined(ACC_CFG_NO_INLINE_ASM)\n#    elif (ACC_ARCH_I386 && (ACC_OS_DOS32 || ACC_OS_WIN32) && (ACC_CC_DMC || ACC_CC_INTELC || ACC_CC_MSC || ACC_CC_PELLESC))\n#        define ACC_ASM_SYNTAX_MSC 1\n#    elif (ACC_OS_WIN64 && (ACC_CC_DMC || ACC_CC_INTELC || ACC_CC_MSC || ACC_CC_PELLESC))\n#    elif (ACC_ARCH_I386 && (ACC_CC_GNUC || ACC_CC_INTELC || ACC_CC_PATHSCALE))\n#        define ACC_ASM_SYNTAX_GNUC 1\n#    elif (ACC_ARCH_AMD64 && (ACC_CC_GNUC || ACC_CC_INTELC || ACC_CC_PATHSCALE))\n#        define ACC_ASM_SYNTAX_GNUC 1\n#    endif\n#    if (ACC_ASM_SYNTAX_GNUC)\n#        if (ACC_ARCH_I386 && ACC_CC_GNUC && (ACC_CC_GNUC < 0x020000ul))\n#            define __ACC_ASM_CLOBBER         \"ax\"\n#        elif (ACC_CC_INTELC)\n#            define __ACC_ASM_CLOBBER         \"memory\"\n#        else\n#            define __ACC_ASM_CLOBBER         \"cc\", \"memory\"\n#        endif\n#    endif\n#    if defined(__ACC_INFOSTR_MM)\n#    elif (ACC_MM_FLAT) && (defined(__ACC_INFOSTR_PM) || defined(ACC_INFO_ABI_PM))\n#        define __ACC_INFOSTR_MM          \"\"\n#    elif defined(ACC_INFO_MM)\n#        define __ACC_INFOSTR_MM          \".\" ACC_INFO_MM\n#    else\n#        define __ACC_INFOSTR_MM          \"\"\n#    endif\n#    if defined(__ACC_INFOSTR_PM)\n#    elif defined(ACC_INFO_ABI_PM)\n#        define __ACC_INFOSTR_PM          \".\" ACC_INFO_ABI_PM\n#    else\n#        define __ACC_INFOSTR_PM          \"\"\n#    endif\n#    if defined(__ACC_INFOSTR_ENDIAN)\n#    elif defined(ACC_INFO_ABI_ENDIAN)\n#        define __ACC_INFOSTR_ENDIAN      \".\" ACC_INFO_ABI_ENDIAN\n#    else\n#        define __ACC_INFOSTR_ENDIAN      \"\"\n#    endif\n#    if defined(__ACC_INFOSTR_OSNAME)\n#    elif defined(ACC_INFO_OS_CONSOLE)\n#        define __ACC_INFOSTR_OSNAME      ACC_INFO_OS \".\" ACC_INFO_OS_CONSOLE\n#    elif defined(ACC_INFO_OS_POSIX)\n#        define __ACC_INFOSTR_OSNAME      ACC_INFO_OS \".\" ACC_INFO_OS_POSIX\n#    else\n#        define __ACC_INFOSTR_OSNAME      ACC_INFO_OS\n#    endif\n#    if defined(__ACC_INFOSTR_LIBC)\n#    elif defined(ACC_INFO_LIBC)\n#        define __ACC_INFOSTR_LIBC        \".\" ACC_INFO_LIBC\n#    else\n#        define __ACC_INFOSTR_LIBC        \"\"\n#    endif\n#    if defined(__ACC_INFOSTR_CCVER)\n#    elif defined(ACC_INFO_CCVER)\n#        define __ACC_INFOSTR_CCVER       \" \" ACC_INFO_CCVER\n#    else\n#        define __ACC_INFOSTR_CCVER       \"\"\n#    endif\n#    define ACC_INFO_STRING \\\n    ACC_INFO_ARCH __ACC_INFOSTR_MM __ACC_INFOSTR_PM __ACC_INFOSTR_ENDIAN \\\n    \" \" __ACC_INFOSTR_OSNAME __ACC_INFOSTR_LIBC \" \" ACC_INFO_CC __ACC_INFOSTR_CCVER\n#    if defined(ACC_CFG_NO_CONFIG_HEADER)\n#    elif defined(ACC_CFG_CONFIG_HEADER)\n#    else\n#        if !defined(ACC_CFG_AUTO_NO_HEADERS)\n#            if defined(ACC_LIBC_NAKED)\n#            elif defined(ACC_LIBC_FREESTANDING)\n#                define HAVE_LIMITS_H 1\n#                define HAVE_STDARG_H 1\n#                define HAVE_STDDEF_H 1\n#            elif defined(ACC_LIBC_MOSTLY_FREESTANDING)\n#                define HAVE_LIMITS_H 1\n#                define HAVE_SETJMP_H 1\n#                define HAVE_STDARG_H 1\n#                define HAVE_STDDEF_H 1\n#                define HAVE_STDIO_H 1\n#                define HAVE_STRING_H 1\n#            else\n#                define STDC_HEADERS 1\n#                define HAVE_ASSERT_H 1\n#                define HAVE_CTYPE_H 1\n#                define HAVE_DIRENT_H 1\n#                define HAVE_ERRNO_H 1\n#                define HAVE_FCNTL_H 1\n#                define HAVE_FLOAT_H 1\n#                define HAVE_LIMITS_H 1\n#                define HAVE_MALLOC_H 1\n#                define HAVE_MEMORY_H 1\n#                define HAVE_SETJMP_H 1\n#                define HAVE_SIGNAL_H 1\n#                define HAVE_STDARG_H 1\n#                define HAVE_STDDEF_H 1\n#                define HAVE_STDIO_H 1\n#                define HAVE_STDLIB_H 1\n#                define HAVE_STRING_H 1\n#                define HAVE_TIME_H 1\n#                define HAVE_UNISTD_H 1\n#                define HAVE_UTIME_H 1\n#                define HAVE_SYS_STAT_H 1\n#                define HAVE_SYS_TIME_H 1\n#                define HAVE_SYS_TYPES_H 1\n#                if (ACC_OS_POSIX)\n#                    if (ACC_OS_POSIX_AIX)\n#                        define HAVE_SYS_RESOURCE_H 1\n#                    elif (ACC_OS_POSIX_FREEBSD || ACC_OS_POSIX_MACOSX || ACC_OS_POSIX_NETBSD || ACC_OS_POSIX_OPENBSD)\n#                        define HAVE_STRINGS_H 1\n#                        undef HAVE_MALLOC_H\n#                    elif (ACC_OS_POSIX_HPUX || ACC_OS_POSIX_INTERIX)\n#                        define HAVE_ALLOCA_H 1\n#                    elif (ACC_OS_POSIX_MACOSX && ACC_LIBC_MSL)\n#                        undef HAVE_SYS_TIME_H\n#                        undef HAVE_SYS_TYPES_H\n#                    elif (ACC_OS_POSIX_SOLARIS || ACC_OS_POSIX_SUNOS)\n#                        define HAVE_ALLOCA_H 1\n#                    endif\n#                    if (ACC_LIBC_DIETLIBC || ACC_LIBC_GLIBC || ACC_LIBC_UCLIBC)\n#                        define HAVE_STRINGS_H 1\n#                        define HAVE_SYS_MMAN_H 1\n#                        define HAVE_SYS_RESOURCE_H 1\n#                        define HAVE_SYS_WAIT_H 1\n#                    endif\n#                    if (ACC_LIBC_NEWLIB)\n#                        undef HAVE_STRINGS_H\n#                    endif\n#                elif (ACC_OS_CYGWIN)\n#                    define HAVE_IO_H 1\n#                elif (ACC_OS_EMX)\n#                    define HAVE_ALLOCA_H 1\n#                    define HAVE_IO_H 1\n#                elif (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC)\n#                    if !defined(__MINT__)\n#                        undef HAVE_MALLOC_H\n#                    endif\n#                elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))\n#                    undef HAVE_DIRENT_H\n#                    undef HAVE_FCNTL_H\n#                    undef HAVE_MALLOC_H\n#                    undef HAVE_MEMORY_H\n#                    undef HAVE_UNISTD_H\n#                    undef HAVE_UTIME_H\n#                    undef HAVE_SYS_STAT_H\n#                    undef HAVE_SYS_TIME_H\n#                    undef HAVE_SYS_TYPES_H\n#                endif\n#                if (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)\n#                    define HAVE_CONIO_H 1\n#                    define HAVE_DIRECT_H 1\n#                    define HAVE_DOS_H 1\n#                    define HAVE_IO_H 1\n#                    define HAVE_SHARE_H 1\n#                    if (ACC_CC_AZTECC)\n#                        undef HAVE_CONIO_H\n#                        undef HAVE_DIRECT_H\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_MALLOC_H\n#                        undef HAVE_SHARE_H\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_UTIME_H\n#                        undef HAVE_SYS_STAT_H\n#                        undef HAVE_SYS_TIME_H\n#                        undef HAVE_SYS_TYPES_H\n#                    elif (ACC_CC_BORLANDC)\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_SYS_TIME_H\n#                        if (ACC_OS_WIN32 || ACC_OS_WIN64)\n#                            undef HAVE_DIRENT_H\n#                        endif\n#                        if (__BORLANDC__ < 0x0400)\n#                            undef HAVE_DIRENT_H\n#                            undef HAVE_UTIME_H\n#                        endif\n#                    elif (ACC_CC_DMC)\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_UNISTD_H\n#                        define HAVE_SYS_DIRENT_H 1\n#                    elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n#                    elif (ACC_OS_DOS32 && ACC_CC_HIGHC)\n#                        define HAVE_ALLOCA_H 1\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_UNISTD_H\n#                    elif (ACC_CC_IBMC && ACC_OS_OS2)\n#                        undef HAVE_DOS_H\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_UTIME_H\n#                        undef HAVE_SYS_TIME_H\n#                        define HAVE_SYS_UTIME_H 1\n#                    elif (ACC_CC_INTELC || ACC_CC_MSC)\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_UTIME_H\n#                        undef HAVE_SYS_TIME_H\n#                        define HAVE_SYS_UTIME_H 1\n#                    elif (ACC_CC_LCCWIN32)\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_DOS_H\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_SYS_TIME_H\n#                    elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__MINGW32__)\n#                        undef HAVE_UTIME_H\n#                        define HAVE_SYS_UTIME_H 1\n#                    elif (ACC_OS_WIN32 && ACC_LIBC_MSL)\n#                        define HAVE_ALLOCA_H 1\n#                        undef HAVE_DOS_H\n#                        undef HAVE_SHARE_H\n#                        undef HAVE_SYS_TIME_H\n#                    elif (ACC_CC_NDPC)\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_DOS_H\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_UTIME_H\n#                        undef HAVE_SYS_TIME_H\n#                    elif (ACC_CC_PACIFICC)\n#                        undef HAVE_DIRECT_H\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_FCNTL_H\n#                        undef HAVE_IO_H\n#                        undef HAVE_MALLOC_H\n#                        undef HAVE_MEMORY_H\n#                        undef HAVE_SHARE_H\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_UTIME_H\n#                        undef HAVE_SYS_STAT_H\n#                        undef HAVE_SYS_TIME_H\n#                        undef HAVE_SYS_TYPES_H\n#                    elif (ACC_OS_WIN32 && ACC_CC_PELLESC)\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_DOS_H\n#                        undef HAVE_MALLOC_H\n#                        undef HAVE_SHARE_H\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_UTIME_H\n#                        undef HAVE_SYS_TIME_H\n#                        if (__POCC__ < 280)\n#                        else\n#                            define HAVE_SYS_UTIME_H 1\n#                        endif\n#                    elif (ACC_OS_WIN32 && ACC_CC_PGI) && defined(__MINGW32__)\n#                        undef HAVE_UTIME_H\n#                        define HAVE_SYS_UTIME_H 1\n#                    elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)\n#                    elif (ACC_CC_SYMANTECC)\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_UNISTD_H\n#                        if (__SC__ < 0x700)\n#                            undef HAVE_UTIME_H\n#                            undef HAVE_SYS_TIME_H\n#                        endif\n#                    elif (ACC_CC_TOPSPEEDC)\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_UTIME_H\n#                        undef HAVE_SYS_STAT_H\n#                        undef HAVE_SYS_TIME_H\n#                        undef HAVE_SYS_TYPES_H\n#                    elif (ACC_CC_TURBOC)\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_SYS_TIME_H\n#                        undef HAVE_SYS_TYPES_H\n#                        if (ACC_OS_WIN32 || ACC_OS_WIN64)\n#                            undef HAVE_DIRENT_H\n#                        endif\n#                        if (__TURBOC__ < 0x0200)\n#                            undef HAVE_SIGNAL_H\n#                        endif\n#                        if (__TURBOC__ < 0x0400)\n#                            undef HAVE_DIRECT_H\n#                            undef HAVE_DIRENT_H\n#                            undef HAVE_MALLOC_H\n#                            undef HAVE_MEMORY_H\n#                            undef HAVE_UTIME_H\n#                        endif\n#                    elif (ACC_CC_WATCOMC)\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_UTIME_H\n#                        undef HAVE_SYS_TIME_H\n#                        define HAVE_SYS_UTIME_H 1\n#                        if (__WATCOMC__ < 950)\n#                            undef HAVE_UNISTD_H\n#                        endif\n#                    elif (ACC_CC_ZORTECHC)\n#                        undef HAVE_DIRENT_H\n#                        undef HAVE_MEMORY_H\n#                        undef HAVE_UNISTD_H\n#                        undef HAVE_UTIME_H\n#                        undef HAVE_SYS_TIME_H\n#                    endif\n#                endif\n#                if (ACC_OS_CONSOLE)\n#                    undef HAVE_DIRENT_H\n#                endif\n#                if (ACC_OS_EMBEDDED)\n#                    undef HAVE_DIRENT_H\n#                endif\n#                if (ACC_LIBC_ISOC90 || ACC_LIBC_ISOC99)\n#                    undef HAVE_DIRENT_H\n#                    undef HAVE_FCNTL_H\n#                    undef HAVE_MALLOC_H\n#                    undef HAVE_UNISTD_H\n#                    undef HAVE_UTIME_H\n#                    undef HAVE_SYS_STAT_H\n#                    undef HAVE_SYS_TIME_H\n#                    undef HAVE_SYS_TYPES_H\n#                endif\n#                if (ACC_LIBC_GLIBC >= 0x020100ul)\n#                    define HAVE_STDINT_H 1\n#                elif (ACC_LIBC_DIETLIBC)\n#                    undef HAVE_STDINT_H\n#                elif (ACC_LIBC_UCLIBC)\n#                    define HAVE_STDINT_H 1\n#                elif (ACC_CC_BORLANDC) && (__BORLANDC__ >= 0x560)\n#                    undef HAVE_STDINT_H\n#                elif (ACC_CC_DMC) && (__DMC__ >= 0x825)\n#                    define HAVE_STDINT_H 1\n#                endif\n#                if (HAVE_SYS_TIME_H && HAVE_TIME_H)\n#                    define TIME_WITH_SYS_TIME 1\n#                endif\n#            endif\n#        endif\n#        if !defined(ACC_CFG_AUTO_NO_FUNCTIONS)\n#            if defined(ACC_LIBC_NAKED)\n#            elif defined(ACC_LIBC_FREESTANDING)\n#            elif defined(ACC_LIBC_MOSTLY_FREESTANDING)\n#                define HAVE_LONGJMP 1\n#                define HAVE_MEMCMP 1\n#                define HAVE_MEMCPY 1\n#                define HAVE_MEMMOVE 1\n#                define HAVE_MEMSET 1\n#                define HAVE_SETJMP 1\n#            else\n#                define HAVE_ACCESS 1\n#                define HAVE_ALLOCA 1\n#                define HAVE_ATEXIT 1\n#                define HAVE_ATOI 1\n#                define HAVE_ATOL 1\n#                define HAVE_CHMOD 1\n#                define HAVE_CHOWN 1\n#                define HAVE_CTIME 1\n#                define HAVE_DIFFTIME 1\n#                define HAVE_FILENO 1\n#                define HAVE_FSTAT 1\n#                define HAVE_GETENV 1\n#                define HAVE_GETTIMEOFDAY 1\n#                define HAVE_GMTIME 1\n#                define HAVE_ISATTY 1\n#                define HAVE_LOCALTIME 1\n#                define HAVE_LONGJMP 1\n#                define HAVE_LSTAT 1\n#                define HAVE_MEMCMP 1\n#                define HAVE_MEMCPY 1\n#                define HAVE_MEMMOVE 1\n#                define HAVE_MEMSET 1\n#                define HAVE_MKDIR 1\n#                define HAVE_MKTIME 1\n#                define HAVE_QSORT 1\n#                define HAVE_RAISE 1\n#                define HAVE_RMDIR 1\n#                define HAVE_SETJMP 1\n#                define HAVE_SIGNAL 1\n#                define HAVE_SNPRINTF 1\n#                define HAVE_STAT 1\n#                define HAVE_STRCHR 1\n#                define HAVE_STRDUP 1\n#                define HAVE_STRERROR 1\n#                define HAVE_STRFTIME 1\n#                define HAVE_STRRCHR 1\n#                define HAVE_STRSTR 1\n#                define HAVE_TIME 1\n#                define HAVE_UMASK 1\n#                define HAVE_UTIME 1\n#                define HAVE_VSNPRINTF 1\n#                if (ACC_OS_BEOS || ACC_OS_CYGWIN || ACC_OS_POSIX || ACC_OS_QNX || ACC_OS_VMS)\n#                    define HAVE_STRCASECMP 1\n#                    define HAVE_STRNCASECMP 1\n#                elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)\n#                    define HAVE_STRCASECMP 1\n#                    define HAVE_STRNCASECMP 1\n#                else\n#                    define HAVE_STRICMP 1\n#                    define HAVE_STRNICMP 1\n#                endif\n#                if (ACC_OS_POSIX)\n#                    if (ACC_OS_POSIX_AIX)\n#                        define HAVE_GETRUSAGE 1\n#                    elif (ACC_OS_POSIX_MACOSX && ACC_LIBC_MSL)\n#                        undef HAVE_CHOWN\n#                        undef HAVE_LSTAT\n#                    elif (ACC_OS_POSIX_UNICOS)\n#                        undef HAVE_ALLOCA\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_VSNPRINTF\n#                    endif\n#                    if (ACC_CC_TINYC)\n#                        undef HAVE_ALLOCA\n#                    endif\n#                    if (ACC_LIBC_DIETLIBC || ACC_LIBC_GLIBC || ACC_LIBC_UCLIBC)\n#                        define HAVE_GETRUSAGE 1\n#                        define HAVE_GETPAGESIZE 1\n#                        define HAVE_MMAP 1\n#                        define HAVE_MPROTECT 1\n#                        define HAVE_MUNMAP 1\n#                    endif\n#                elif (ACC_OS_CYGWIN)\n#                    if (ACC_CC_GNUC < 0x025a00ul)\n#                        undef HAVE_GETTIMEOFDAY\n#                        undef HAVE_LSTAT\n#                    endif\n#                    if (ACC_CC_GNUC < 0x025f00ul)\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_VSNPRINTF\n#                    endif\n#                elif (ACC_OS_EMX)\n#                    undef HAVE_CHOWN\n#                    undef HAVE_LSTAT\n#                elif (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC)\n#                    if !defined(__MINT__)\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_VSNPRINTF\n#                    endif\n#                elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))\n#                    undef HAVE_ALLOCA\n#                    undef HAVE_ACCESS\n#                    undef HAVE_CHMOD\n#                    undef HAVE_CHOWN\n#                    undef HAVE_FSTAT\n#                    undef HAVE_GETTIMEOFDAY\n#                    undef HAVE_LSTAT\n#                    undef HAVE_SNPRINTF\n#                    undef HAVE_UMASK\n#                    undef HAVE_UTIME\n#                    undef HAVE_VSNPRINTF\n#                endif\n#                if (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)\n#                    undef HAVE_CHOWN\n#                    undef HAVE_GETTIMEOFDAY\n#                    undef HAVE_LSTAT\n#                    undef HAVE_UMASK\n#                    if (ACC_CC_AZTECC)\n#                        undef HAVE_ALLOCA\n#                        undef HAVE_DIFFTIME\n#                        undef HAVE_FSTAT\n#                        undef HAVE_STRDUP\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_UTIME\n#                        undef HAVE_VSNPRINTF\n#                    elif (ACC_CC_BORLANDC)\n#                        if (__BORLANDC__ < 0x0400)\n#                            undef HAVE_ALLOCA\n#                            undef HAVE_UTIME\n#                        endif\n#                        if ((__BORLANDC__ < 0x0410) && ACC_OS_WIN16)\n#                            undef HAVE_ALLOCA\n#                        endif\n#                        if (__BORLANDC__ < 0x0550)\n#                            undef HAVE_SNPRINTF\n#                            undef HAVE_VSNPRINTF\n#                        endif\n#                    elif (ACC_CC_DMC)\n#                        if (ACC_OS_WIN16)\n#                            undef HAVE_ALLOCA\n#                        endif\n#                        define snprintf _snprintf\n#                        define vsnprintf _vsnprintf\n#                    elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_VSNPRINTF\n#                    elif (ACC_OS_DOS32 && ACC_CC_HIGHC)\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_VSNPRINTF\n#                    elif (ACC_CC_IBMC)\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_VSNPRINTF\n#                    elif (ACC_CC_INTELC)\n#                        define snprintf _snprintf\n#                        define vsnprintf _vsnprintf\n#                    elif (ACC_CC_LCCWIN32)\n#                        define utime _utime\n#                    elif (ACC_CC_MSC)\n#                        if (_MSC_VER < 600)\n#                            undef HAVE_STRFTIME\n#                        endif\n#                        if (_MSC_VER < 700)\n#                            undef HAVE_SNPRINTF\n#                            undef HAVE_VSNPRINTF\n#                        elif (_MSC_VER < 1500)\n#                            define snprintf _snprintf\n#                            define vsnprintf _vsnprintf\n#                        endif\n#                        if ((_MSC_VER < 800) && ACC_OS_WIN16)\n#                            undef HAVE_ALLOCA\n#                        endif\n#                        if (ACC_ARCH_I086) && defined(__cplusplus)\n#                            undef HAVE_LONGJMP\n#                            undef HAVE_SETJMP\n#                        endif\n#                    elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__MINGW32__)\n#                        if (ACC_CC_GNUC < 0x025f00ul)\n#                            undef HAVE_SNPRINTF\n#                            undef HAVE_VSNPRINTF\n#                        else\n#                            define snprintf _snprintf\n#                            define vsnprintf _vsnprintf\n#                        endif\n#                    elif (ACC_OS_WIN32 && ACC_LIBC_MSL)\n#                        if (__MSL__ < 0x8000ul)\n#                            undef HAVE_CHMOD\n#                        endif\n#                    elif (ACC_CC_NDPC)\n#                        undef HAVE_ALLOCA\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_STRNICMP\n#                        undef HAVE_UTIME\n#                        undef HAVE_VSNPRINTF\n#                        if defined(__cplusplus)\n#                            undef HAVE_STAT\n#                        endif\n#                    elif (ACC_CC_PACIFICC)\n#                        undef HAVE_ACCESS\n#                        undef HAVE_ALLOCA\n#                        undef HAVE_CHMOD\n#                        undef HAVE_DIFFTIME\n#                        undef HAVE_FSTAT\n#                        undef HAVE_MKTIME\n#                        undef HAVE_RAISE\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_STRFTIME\n#                        undef HAVE_UTIME\n#                        undef HAVE_VSNPRINTF\n#                    elif (ACC_OS_WIN32 && ACC_CC_PELLESC)\n#                        if (__POCC__ < 280)\n#                            define alloca _alloca\n#                            undef HAVE_UTIME\n#                        endif\n#                    elif (ACC_OS_WIN32 && ACC_CC_PGI) && defined(__MINGW32__)\n#                        define snprintf _snprintf\n#                        define vsnprintf _vsnprintf\n#                    elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_VSNPRINTF\n#                    elif (ACC_CC_SYMANTECC)\n#                        if (ACC_OS_WIN16 && (ACC_MM_MEDIUM || ACC_MM_LARGE || ACC_MM_HUGE))\n#                            undef HAVE_ALLOCA\n#                        endif\n#                        if (__SC__ < 0x600)\n#                            undef HAVE_SNPRINTF\n#                            undef HAVE_VSNPRINTF\n#                        else\n#                            define snprintf _snprintf\n#                            define vsnprintf _vsnprintf\n#                        endif\n#                        if (__SC__ < 0x700)\n#                            undef HAVE_DIFFTIME\n#                            undef HAVE_UTIME\n#                        endif\n#                    elif (ACC_CC_TOPSPEEDC)\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_VSNPRINTF\n#                    elif (ACC_CC_TURBOC)\n#                        undef HAVE_ALLOCA\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_VSNPRINTF\n#                        if (__TURBOC__ < 0x0200)\n#                            undef HAVE_RAISE\n#                            undef HAVE_SIGNAL\n#                        endif\n#                        if (__TURBOC__ < 0x0295)\n#                            undef HAVE_MKTIME\n#                            undef HAVE_STRFTIME\n#                        endif\n#                        if (__TURBOC__ < 0x0400)\n#                            undef HAVE_UTIME\n#                        endif\n#                    elif (ACC_CC_WATCOMC)\n#                        if (__WATCOMC__ < 1100)\n#                            undef HAVE_SNPRINTF\n#                            undef HAVE_VSNPRINTF\n#                        elif (__WATCOMC__ < 1200)\n#                            define snprintf _snprintf\n#                            define vsnprintf _vsnprintf\n#                        endif\n#                    elif (ACC_CC_ZORTECHC)\n#                        if (ACC_OS_WIN16 && (ACC_MM_MEDIUM || ACC_MM_LARGE || ACC_MM_HUGE))\n#                            undef HAVE_ALLOCA\n#                        endif\n#                        undef HAVE_DIFFTIME\n#                        undef HAVE_SNPRINTF\n#                        undef HAVE_UTIME\n#                        undef HAVE_VSNPRINTF\n#                    endif\n#                endif\n#                if (ACC_OS_CONSOLE)\n#                    undef HAVE_ACCESS\n#                    undef HAVE_CHMOD\n#                    undef HAVE_CHOWN\n#                    undef HAVE_GETTIMEOFDAY\n#                    undef HAVE_LSTAT\n#                    undef HAVE_TIME\n#                    undef HAVE_UMASK\n#                    undef HAVE_UTIME\n#                endif\n#                if (ACC_LIBC_ISOC90 || ACC_LIBC_ISOC99)\n#                    undef HAVE_ACCESS\n#                    undef HAVE_CHMOD\n#                    undef HAVE_CHOWN\n#                    undef HAVE_FSTAT\n#                    undef HAVE_GETTIMEOFDAY\n#                    undef HAVE_LSTAT\n#                    undef HAVE_STAT\n#                    undef HAVE_UMASK\n#                    undef HAVE_UTIME\n#                    if 1\n#                        undef HAVE_ALLOCA\n#                        undef HAVE_ISATTY\n#                        undef HAVE_MKDIR\n#                        undef HAVE_RMDIR\n#                        undef HAVE_STRDUP\n#                        undef HAVE_STRICMP\n#                        undef HAVE_STRNICMP\n#                    endif\n#                endif\n#            endif\n#        endif\n#        if !defined(ACC_CFG_AUTO_NO_SIZES)\n#            if !defined(SIZEOF_SHORT) && defined(ACC_SIZEOF_SHORT)\n#                define SIZEOF_SHORT          ACC_SIZEOF_SHORT\n#            endif\n#            if !defined(SIZEOF_INT) && defined(ACC_SIZEOF_INT)\n#                define SIZEOF_INT            ACC_SIZEOF_INT\n#            endif\n#            if !defined(SIZEOF_LONG) && defined(ACC_SIZEOF_LONG)\n#                define SIZEOF_LONG           ACC_SIZEOF_LONG\n#            endif\n#            if !defined(SIZEOF_LONG_LONG) && defined(ACC_SIZEOF_LONG_LONG)\n#                define SIZEOF_LONG_LONG      ACC_SIZEOF_LONG_LONG\n#            endif\n#            if !defined(SIZEOF___INT32) && defined(ACC_SIZEOF___INT32)\n#                define SIZEOF___INT32        ACC_SIZEOF___INT32\n#            endif\n#            if !defined(SIZEOF___INT64) && defined(ACC_SIZEOF___INT64)\n#                define SIZEOF___INT64        ACC_SIZEOF___INT64\n#            endif\n#            if !defined(SIZEOF_VOID_P) && defined(ACC_SIZEOF_VOID_P)\n#                define SIZEOF_VOID_P         ACC_SIZEOF_VOID_P\n#            endif\n#            if !defined(SIZEOF_SIZE_T) && defined(ACC_SIZEOF_SIZE_T)\n#                define SIZEOF_SIZE_T         ACC_SIZEOF_SIZE_T\n#            endif\n#            if !defined(SIZEOF_PTRDIFF_T) && defined(ACC_SIZEOF_PTRDIFF_T)\n#                define SIZEOF_PTRDIFF_T      ACC_SIZEOF_PTRDIFF_T\n#            endif\n#        endif\n#        if defined(HAVE_SIGNAL) && !defined(RETSIGTYPE)\n#            define RETSIGTYPE void\n#        endif\n#    endif\n#    if defined(ACC_CFG_NO_ACC_TYPE_H)\n#    else\n#        if (ACC_SIZEOF_LONG_LONG+0 > 0)\n__acc_gnuc_extension__ typedef long long acc_llong_t;\n__acc_gnuc_extension__ typedef unsigned long long acc_ullong_t;\n#        endif\n#        if (!(ACC_SIZEOF_SHORT+0 > 0 && ACC_SIZEOF_INT+0 > 0 && ACC_SIZEOF_LONG+0 > 0))\n#            error \"missing defines for sizes\"\n#        endif\n#        if (!(ACC_SIZEOF_PTRDIFF_T+0 > 0 && ACC_SIZEOF_SIZE_T+0 > 0 && ACC_SIZEOF_VOID_P+0 > 0))\n#            error \"missing defines for sizes\"\n#        endif\n#        if !defined(acc_int16e_t)\n#            if (ACC_SIZEOF_LONG == 2)\n#                define acc_int16e_t          long\n#                define acc_uint16e_t         unsigned long\n#            elif (ACC_SIZEOF_INT == 2)\n#                define acc_int16e_t          int\n#                define acc_uint16e_t         unsigned int\n#            elif (ACC_SIZEOF_SHORT == 2)\n#                define acc_int16e_t          short int\n#                define acc_uint16e_t         unsigned short int\n#            elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_HI) && (ACC_CC_GNUC >= 0x025f00ul || ACC_CC_LLVM)\ntypedef int __acc_int16e_hi_t __attribute__ ((__mode__(__HI__)));\ntypedef unsigned int __acc_uint16e_hi_t __attribute__ ((__mode__(__HI__)));\n#                define acc_int16e_t          __acc_int16e_hi_t\n#                define acc_uint16e_t         __acc_uint16e_hi_t\n#            elif (ACC_SIZEOF___INT16 == 2)\n#                define acc_int16e_t          __int16\n#                define acc_uint16e_t         unsigned __int16\n#            else\n#            endif\n#        endif\n#        if defined(acc_int16e_t)\n#            define ACC_SIZEOF_ACC_INT16E_T   2\n#        endif\n#        if !defined(acc_int32e_t)\n#            if (ACC_SIZEOF_LONG == 4)\n#                define acc_int32e_t          long int\n#                define acc_uint32e_t         unsigned long int\n#            elif (ACC_SIZEOF_INT == 4)\n#                define acc_int32e_t          int\n#                define acc_uint32e_t         unsigned int\n#            elif (ACC_SIZEOF_SHORT == 4)\n#                define acc_int32e_t          short int\n#                define acc_uint32e_t         unsigned short int\n#            elif (ACC_SIZEOF_LONG_LONG == 4)\n#                define acc_int32e_t          acc_llong_t\n#                define acc_uint32e_t         acc_ullong_t\n#            elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_SI) && (ACC_CC_GNUC >= 0x025f00ul || ACC_CC_LLVM) && (__INT_MAX__+0 > 2147483647L)\ntypedef int __acc_int32e_si_t __attribute__ ((__mode__(__SI__)));\ntypedef unsigned int __acc_uint32e_si_t __attribute__ ((__mode__(__SI__)));\n#                define acc_int32e_t          __acc_int32e_si_t\n#                define acc_uint32e_t         __acc_uint32e_si_t\n#            elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_SI) && (ACC_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L)\ntypedef int __acc_int32e_si_t __attribute__ ((__mode__(__SI__)));\ntypedef unsigned int __acc_uint32e_si_t __attribute__ ((__mode__(__SI__)));\n#                define acc_int32e_t          __acc_int32e_si_t\n#                define acc_uint32e_t         __acc_uint32e_si_t\n#                define ACC_INT32_C(c)        c##LL\n#                define ACC_UINT32_C(c)       c##ULL\n#            elif (ACC_SIZEOF___INT32 == 4)\n#                define acc_int32e_t          __int32\n#                define acc_uint32e_t         unsigned __int32\n#            else\n#            endif\n#        endif\n#        if defined(acc_int32e_t)\n#            define ACC_SIZEOF_ACC_INT32E_T   4\n#        endif\n#        if !defined(acc_int64e_t)\n#            if (ACC_SIZEOF___INT64 == 8)\n#                if (ACC_CC_BORLANDC) && !defined(ACC_CFG_TYPE_PREFER___INT64)\n#                    define ACC_CFG_TYPE_PREFER___INT64 1\n#                endif\n#            endif\n#            if (ACC_SIZEOF_INT == 8) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)\n#                define acc_int64e_t          int\n#                define acc_uint64e_t         unsigned int\n#                define ACC_SIZEOF_ACC_INT64E_T   ACC_SIZEOF_INT\n#            elif (ACC_SIZEOF_LONG == 8)\n#                define acc_int64e_t          long int\n#                define acc_uint64e_t         unsigned long int\n#                define ACC_SIZEOF_ACC_INT64E_T   ACC_SIZEOF_LONG\n#            elif (ACC_SIZEOF_LONG_LONG == 8) && !defined(ACC_CFG_TYPE_PREFER___INT64)\n#                define acc_int64e_t          acc_llong_t\n#                define acc_uint64e_t         acc_ullong_t\n#                if (ACC_CC_BORLANDC)\n#                    define ACC_INT64_C(c)      ((c) + 0ll)\n#                    define ACC_UINT64_C(c)     ((c) + 0ull)\n#                else\n#                    define ACC_INT64_C(c)      c##LL\n#                    define ACC_UINT64_C(c)     c##ULL\n#                endif\n#                define ACC_SIZEOF_ACC_INT64E_T   ACC_SIZEOF_LONG_LONG\n#            elif (ACC_SIZEOF___INT64 == 8)\n#                define acc_int64e_t          __int64\n#                define acc_uint64e_t         unsigned __int64\n#                if (ACC_CC_BORLANDC)\n#                    define ACC_INT64_C(c)      ((c) + 0i64)\n#                    define ACC_UINT64_C(c)     ((c) + 0ui64)\n#                else\n#                    define ACC_INT64_C(c)      c##i64\n#                    define ACC_UINT64_C(c)     c##ui64\n#                endif\n#                define ACC_SIZEOF_ACC_INT64E_T   ACC_SIZEOF___INT64\n#            else\n#            endif\n#        endif\n#        if !defined(acc_int32l_t)\n#            if defined(acc_int32e_t)\n#                define acc_int32l_t          acc_int32e_t\n#                define acc_uint32l_t         acc_uint32e_t\n#                define ACC_SIZEOF_ACC_INT32L_T   ACC_SIZEOF_ACC_INT32E_T\n#            elif (ACC_SIZEOF_INT >= 4) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)\n#                define acc_int32l_t          int\n#                define acc_uint32l_t         unsigned int\n#                define ACC_SIZEOF_ACC_INT32L_T   ACC_SIZEOF_INT\n#            elif (ACC_SIZEOF_LONG >= 4)\n#                define acc_int32l_t          long int\n#                define acc_uint32l_t         unsigned long int\n#                define ACC_SIZEOF_ACC_INT32L_T   ACC_SIZEOF_LONG\n#            else\n#                error \"acc_int32l_t\"\n#            endif\n#        endif\n#        if !defined(acc_int64l_t)\n#            if defined(acc_int64e_t)\n#                define acc_int64l_t          acc_int64e_t\n#                define acc_uint64l_t         acc_uint64e_t\n#                define ACC_SIZEOF_ACC_INT64L_T   ACC_SIZEOF_ACC_INT64E_T\n#            else\n#            endif\n#        endif\n#        if !defined(acc_int32f_t)\n#            if (ACC_SIZEOF_SIZE_T >= 8)\n#                define acc_int32f_t          acc_int64l_t\n#                define acc_uint32f_t         acc_uint64l_t\n#                define ACC_SIZEOF_ACC_INT32F_T   ACC_SIZEOF_ACC_INT64L_T\n#            else\n#                define acc_int32f_t          acc_int32l_t\n#                define acc_uint32f_t         acc_uint32l_t\n#                define ACC_SIZEOF_ACC_INT32F_T   ACC_SIZEOF_ACC_INT32L_T\n#            endif\n#        endif\n#        if !defined(acc_intptr_t)\n#            if 1 && (ACC_OS_OS400 && (ACC_SIZEOF_VOID_P == 16))\n#                define __ACC_INTPTR_T_IS_POINTER 1\ntypedef char *acc_intptr_t;\ntypedef char *acc_uintptr_t;\n#                define acc_intptr_t          acc_intptr_t\n#                define acc_uintptr_t         acc_uintptr_t\n#                define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_VOID_P\n#            elif (ACC_CC_MSC && (_MSC_VER >= 1300) && (ACC_SIZEOF_VOID_P == 4) && (ACC_SIZEOF_INT == 4))\ntypedef __w64 int acc_intptr_t;\ntypedef __w64 unsigned int acc_uintptr_t;\n#                define acc_intptr_t          acc_intptr_t\n#                define acc_uintptr_t         acc_uintptr_t\n#                define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_INT\n#            elif (ACC_SIZEOF_SHORT == ACC_SIZEOF_VOID_P) && (ACC_SIZEOF_INT > ACC_SIZEOF_VOID_P)\n#                define acc_intptr_t          short\n#                define acc_uintptr_t         unsigned short\n#                define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_SHORT\n#            elif (ACC_SIZEOF_INT >= ACC_SIZEOF_VOID_P) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)\n#                define acc_intptr_t          int\n#                define acc_uintptr_t         unsigned int\n#                define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_INT\n#            elif (ACC_SIZEOF_LONG >= ACC_SIZEOF_VOID_P)\n#                define acc_intptr_t          long\n#                define acc_uintptr_t         unsigned long\n#                define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_LONG\n#            elif (ACC_SIZEOF_ACC_INT64L_T >= ACC_SIZEOF_VOID_P)\n#                define acc_intptr_t          acc_int64l_t\n#                define acc_uintptr_t         acc_uint64l_t\n#                define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_ACC_INT64L_T\n#            else\n#                error \"acc_intptr_t\"\n#            endif\n#        endif\n#        if !defined(acc_word_t)\n#            if defined(ACC_WORDSIZE) && (ACC_WORDSIZE > 0)\n#                if (ACC_WORDSIZE == ACC_SIZEOF_ACC_INTPTR_T) && !defined(__ACC_INTPTR_T_IS_POINTER)\n#                    define acc_word_t            acc_uintptr_t\n#                    define acc_sword_t           acc_intptr_t\n#                    define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_INTPTR_T\n#                elif (ACC_WORDSIZE == ACC_SIZEOF_LONG)\n#                    define acc_word_t            unsigned long\n#                    define acc_sword_t           long\n#                    define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_LONG\n#                elif (ACC_WORDSIZE == ACC_SIZEOF_INT)\n#                    define acc_word_t            unsigned int\n#                    define acc_sword_t           int\n#                    define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_INT\n#                elif (ACC_WORDSIZE == ACC_SIZEOF_SHORT)\n#                    define acc_word_t            unsigned short\n#                    define acc_sword_t           short\n#                    define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_SHORT\n#                elif (ACC_WORDSIZE == 1)\n#                    define acc_word_t            unsigned char\n#                    define acc_sword_t           signed char\n#                    define ACC_SIZEOF_ACC_WORD_T 1\n#                elif (ACC_WORDSIZE == ACC_SIZEOF_ACC_INT64L_T)\n#                    define acc_word_t            acc_uint64l_t\n#                    define acc_sword_t           acc_int64l_t\n#                    define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_INT64L_T\n#                elif (ACC_ARCH_SPU) && (ACC_CC_GNUC)\n#                    if 0\ntypedef unsigned acc_word_t __attribute__ ((__mode__(__V16QI__)));\ntypedef int acc_sword_t __attribute__ ((__mode__(__V16QI__)));\n#                        define acc_word_t            acc_word_t\n#                        define acc_sword_t           acc_sword_t\n#                        define ACC_SIZEOF_ACC_WORD_T 16\n#                    endif\n#                else\n#                    error \"acc_word_t\"\n#                endif\n#            endif\n#        endif\n#        if !defined(ACC_INT16_C)\n#            if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 2)\n#                define ACC_INT16_C(c)      ((c) + 0)\n#                define ACC_UINT16_C(c)     ((c) + 0U)\n#            elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 2)\n#                define ACC_INT16_C(c)      ((c) + 0L)\n#                define ACC_UINT16_C(c)     ((c) + 0UL)\n#            elif (ACC_SIZEOF_INT >= 2)\n#                define ACC_INT16_C(c)      c\n#                define ACC_UINT16_C(c)     c##U\n#            elif (ACC_SIZEOF_LONG >= 2)\n#                define ACC_INT16_C(c)      c##L\n#                define ACC_UINT16_C(c)     c##UL\n#            else\n#                error \"ACC_INT16_C\"\n#            endif\n#        endif\n#        if !defined(ACC_INT32_C)\n#            if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 4)\n#                define ACC_INT32_C(c)      ((c) + 0)\n#                define ACC_UINT32_C(c)     ((c) + 0U)\n#            elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 4)\n#                define ACC_INT32_C(c)      ((c) + 0L)\n#                define ACC_UINT32_C(c)     ((c) + 0UL)\n#            elif (ACC_SIZEOF_INT >= 4)\n#                define ACC_INT32_C(c)      c\n#                define ACC_UINT32_C(c)     c##U\n#            elif (ACC_SIZEOF_LONG >= 4)\n#                define ACC_INT32_C(c)      c##L\n#                define ACC_UINT32_C(c)     c##UL\n#            elif (ACC_SIZEOF_LONG_LONG >= 4)\n#                define ACC_INT32_C(c)      c##LL\n#                define ACC_UINT32_C(c)     c##ULL\n#            else\n#                error \"ACC_INT32_C\"\n#            endif\n#        endif\n#        if !defined(ACC_INT64_C) && defined(acc_int64l_t)\n#            if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 8)\n#                define ACC_INT64_C(c)      ((c) + 0)\n#                define ACC_UINT64_C(c)     ((c) + 0U)\n#            elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 8)\n#                define ACC_INT64_C(c)      ((c) + 0L)\n#                define ACC_UINT64_C(c)     ((c) + 0UL)\n#            elif (ACC_SIZEOF_INT >= 8)\n#                define ACC_INT64_C(c)      c\n#                define ACC_UINT64_C(c)     c##U\n#            elif (ACC_SIZEOF_LONG >= 8)\n#                define ACC_INT64_C(c)      c##L\n#                define ACC_UINT64_C(c)     c##UL\n#            else\n#                error \"ACC_INT64_C\"\n#            endif\n#        endif\n#        if !defined(SIZEOF_ACC_INT16E_T) && defined(ACC_SIZEOF_ACC_INT16E_T)\n#            define SIZEOF_ACC_INT16E_T   ACC_SIZEOF_ACC_INT16E_T\n#        endif\n#        if !defined(SIZEOF_ACC_INT32E_T) && defined(ACC_SIZEOF_ACC_INT32E_T)\n#            define SIZEOF_ACC_INT32E_T   ACC_SIZEOF_ACC_INT32E_T\n#        endif\n#        if !defined(SIZEOF_ACC_INT64E_T) && defined(ACC_SIZEOF_ACC_INT64E_T)\n#            define SIZEOF_ACC_INT64E_T   ACC_SIZEOF_ACC_INT64E_T\n#        endif\n#        if !defined(SIZEOF_ACC_INT32L_T) && defined(ACC_SIZEOF_ACC_INT32L_T)\n#            define SIZEOF_ACC_INT32L_T   ACC_SIZEOF_ACC_INT32L_T\n#        endif\n#        if !defined(SIZEOF_ACC_INT64L_T) && defined(ACC_SIZEOF_ACC_INT64L_T)\n#            define SIZEOF_ACC_INT64L_T   ACC_SIZEOF_ACC_INT64L_T\n#        endif\n#        if !defined(SIZEOF_ACC_INT32F_T) && defined(ACC_SIZEOF_ACC_INT32F_T)\n#            define SIZEOF_ACC_INT32F_T   ACC_SIZEOF_ACC_INT32F_T\n#        endif\n#        if !defined(SIZEOF_ACC_INTPTR_T) && defined(ACC_SIZEOF_ACC_INTPTR_T)\n#            define SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_ACC_INTPTR_T\n#        endif\n#        if !defined(SIZEOF_ACC_WORD_T) && defined(ACC_SIZEOF_ACC_WORD_T)\n#            define SIZEOF_ACC_WORD_T     ACC_SIZEOF_ACC_WORD_T\n#        endif\n#        if 1 && !defined(acc_signo_t) && defined(__linux__) && defined(__dietlibc__) && (ACC_SIZEOF_INT != 4)\n#            define acc_signo_t           acc_int32e_t\n#        endif\n#        if !defined(acc_signo_t)\n#            define acc_signo_t           int\n#        endif\n#        if defined(__cplusplus)\nextern \"C\" {\n#        endif\n#        if (ACC_BROKEN_CDECL_ALT_SYNTAX)\n\ttypedef void __acc_cdecl_sighandler(*acc_sighandler_t) (acc_signo_t);\n#        elif defined(RETSIGTYPE)\n\ttypedef RETSIGTYPE(__acc_cdecl_sighandler * acc_sighandler_t) (acc_signo_t);\n#        else\n\ttypedef void (__acc_cdecl_sighandler * acc_sighandler_t) (acc_signo_t);\n#        endif\n#        if defined(__cplusplus)\n}\n#        endif\n#        if defined(ACC_CFG_NO_ACC_UA_H)\n#        else\n#            if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020700ul))\n#            elif (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020800ul)) && defined(__cplusplus)\n#            elif (ACC_CC_INTELC) && defined(_WIN32)\n#            elif (ACC_CC_INTELC && (__INTEL_COMPILER < 700))\n#            elif (ACC_CC_LLVM)\n#            elif (ACC_CC_GNUC || ACC_CC_INTELC || ACC_CC_PATHSCALE)\n#                if !defined(__acc_ua16_t) && (ACC_OPT_UNALIGNED16) && defined(acc_int16e_t)\ntypedef struct {\n\t__acc_ua_volatile acc_uint16e_t v __attribute__ ((__packed__));\n} __acc_ua16_t;\n#                    define __acc_ua16_t __acc_ua16_t\n#                endif\n#                if !defined(__acc_ua32_t) && (ACC_OPT_UNALIGNED32) && defined(acc_int32e_t)\ntypedef struct {\n\t__acc_ua_volatile acc_uint32e_t v __attribute__ ((__packed__));\n} __acc_ua32_t;\n#                    define __acc_ua32_t __acc_ua32_t\n#                endif\n#                if !defined(__acc_ua64_t) && (ACC_OPT_UNALIGNED64) && defined(acc_int64l_t)\ntypedef struct {\n\t__acc_ua_volatile acc_uint64l_t v __attribute__ ((__packed__));\n} __acc_ua64_t;\n#                    define __acc_ua64_t __acc_ua64_t\n#                endif\n#            endif\n#            if (ACC_OPT_UNALIGNED16) && defined(acc_int16e_t)\n#                define ACC_UA_GET16(p)         (* (__acc_ua_volatile const acc_uint16e_t*) (__acc_ua_volatile const void*) (p))\n#                define ACC_UA_SET16(p,v)       (* (__acc_ua_volatile acc_uint16e_t*) (__acc_ua_volatile void*) (p) = (acc_uint16e_t) (v))\n#                if (ACC_ABI_BIG_ENDIAN)\n#                    define ACC_UA_GET_BE16(p)    ACC_UA_GET16(p)\n#                    define ACC_UA_SET_BE16(p,v)  ACC_UA_SET16(p,v)\n#                elif (ACC_ABI_LITTLE_ENDIAN)\n#                    define ACC_UA_GET_LE16(p)    ACC_UA_GET16(p)\n#                    define ACC_UA_SET_LE16(p,v)  ACC_UA_SET16(p,v)\n#                endif\n#                if !defined(ACC_CFG_NO_INLINE_ASM) && defined(__acc_HAVE_forceinline)\n#                    if (ACC_ARCH_POWERPC && ACC_ABI_BIG_ENDIAN) && (ACC_CC_GNUC)\n#                        if !defined(ACC_UA_GET_LE16)\nextern __acc_forceinline unsigned long __ACC_UA_GET_LE16(__acc_ua_volatile const void *pp);\nextern __acc_forceinline unsigned long __ACC_UA_GET_LE16(__acc_ua_volatile const void *pp) {\n\t__acc_ua_volatile const acc_uint16e_t *p = (__acc_ua_volatile const acc_uint16e_t *)pp;\n\tunsigned long v;\n\t__asm__ __volatile__(\"lhbrx %0,0,%1\":\"=r\"(v):\"r\"(p), \"m\"(*p));\n\treturn v;\n}\n\n#                            define ACC_UA_GET_LE16(p)      __ACC_UA_GET_LE16(p)\n#                        endif\n#                        if !defined(ACC_UA_SET_LE16)\nextern __acc_forceinline void __ACC_UA_SET_LE16(__acc_ua_volatile void *pp, unsigned long v);\nextern __acc_forceinline void __ACC_UA_SET_LE16(__acc_ua_volatile void *pp, unsigned long v) {\n\t__acc_ua_volatile acc_uint16e_t *p = (__acc_ua_volatile acc_uint16e_t *) pp;\n\t__asm__ __volatile__(\"sthbrx %2,0,%1\":\"=m\"(*p):\"r\"(p), \"r\"(v));\n}\n\n#                            define ACC_UA_SET_LE16(p,v)    __ACC_UA_SET_LE16(p,v)\n#                        endif\n#                    endif\n#                endif\n#                if !defined(ACC_UA_COPY16)\n#                    define ACC_UA_COPY16(d,s)    ACC_UA_SET16(d, ACC_UA_GET16(s))\n#                endif\n#            endif\n#            if (ACC_OPT_UNALIGNED32) && defined(acc_int32e_t)\n#                define ACC_UA_GET32(p)         (* (__acc_ua_volatile const acc_uint32e_t*) (__acc_ua_volatile const void*) (p))\n#                define ACC_UA_SET32(p,v)       (* (__acc_ua_volatile acc_uint32e_t*) (__acc_ua_volatile void*) (p) = (acc_uint32e_t) (v))\n#                if (ACC_ABI_BIG_ENDIAN)\n#                    define ACC_UA_GET_BE32(p)    ACC_UA_GET32(p)\n#                    define ACC_UA_SET_BE32(p,v)  ACC_UA_SET32(p,v)\n#                elif (ACC_ABI_LITTLE_ENDIAN)\n#                    define ACC_UA_GET_LE32(p)    ACC_UA_GET32(p)\n#                    define ACC_UA_SET_LE32(p,v)  ACC_UA_SET32(p,v)\n#                endif\n#                if !defined(ACC_CFG_NO_INLINE_ASM) && defined(__acc_HAVE_forceinline)\n#                    if (ACC_ARCH_POWERPC && ACC_ABI_BIG_ENDIAN) && (ACC_CC_GNUC)\n#                        if !defined(ACC_UA_GET_LE32)\nextern __acc_forceinline unsigned long __ACC_UA_GET_LE32(__acc_ua_volatile const void *pp);\nextern __acc_forceinline unsigned long __ACC_UA_GET_LE32(__acc_ua_volatile const void *pp) {\n\t__acc_ua_volatile const acc_uint32e_t *p = (__acc_ua_volatile const acc_uint32e_t *)pp;\n\tunsigned long v;\n\t__asm__ __volatile__(\"lwbrx %0,0,%1\":\"=r\"(v):\"r\"(p), \"m\"(*p));\n\treturn v;\n}\n\n#                            define ACC_UA_GET_LE32(p)      __ACC_UA_GET_LE32(p)\n#                        endif\n#                        if !defined(ACC_UA_SET_LE32)\nextern __acc_forceinline void __ACC_UA_SET_LE32(__acc_ua_volatile void *pp, unsigned long v);\nextern __acc_forceinline void __ACC_UA_SET_LE32(__acc_ua_volatile void *pp, unsigned long v) {\n\t__acc_ua_volatile acc_uint32e_t *p = (__acc_ua_volatile acc_uint32e_t *) pp;\n\t__asm__ __volatile__(\"stwbrx %2,0,%1\":\"=m\"(*p):\"r\"(p), \"r\"(v));\n}\n\n#                            define ACC_UA_SET_LE32(p,v)    __ACC_UA_SET_LE32(p,v)\n#                        endif\n#                    endif\n#                endif\n#                if !defined(ACC_UA_COPY32)\n#                    define ACC_UA_COPY32(d,s)    ACC_UA_SET32(d, ACC_UA_GET32(s))\n#                endif\n#            endif\n#            if (ACC_OPT_UNALIGNED64) && defined(acc_int64l_t)\n#                define ACC_UA_GET64(p)         (* (__acc_ua_volatile const acc_uint64l_t*) (__acc_ua_volatile const void*) (p))\n#                define ACC_UA_SET64(p,v)       (* (__acc_ua_volatile acc_uint64l_t*) (__acc_ua_volatile void*) (p) = (acc_uint64l_t) (v))\n#                if (ACC_ABI_BIG_ENDIAN)\n#                    define ACC_UA_GET_BE64(p)    ACC_UA_GET64(p)\n#                    define ACC_UA_SET_BE64(p,v)  ACC_UA_SET64(p,v)\n#                elif (ACC_ABI_LITTLE_ENDIAN)\n#                    define ACC_UA_GET_LE64(p)    ACC_UA_GET64(p)\n#                    define ACC_UA_SET_LE64(p,v)  ACC_UA_SET64(p,v)\n#                endif\n#                if !defined(ACC_UA_COPY64)\n#                    define ACC_UA_COPY64(d,s)    ACC_UA_SET64(d, ACC_UA_GET64(s))\n#                endif\n#            endif\n#        endif\n#    endif\n#endif\n#if defined(ACC_WANT_ACC_TYPE_H)\n#    undef ACC_WANT_ACC_TYPE_H\n#    if defined(ACC_CFG_NO_ACC_TYPE_H)\n#        error \"ACC_WANT_ACC_TYPE_H with ACC_CFG_NO_ACC_TYPE_H\"\n#    endif\n#    if (ACC_SIZEOF_LONG_LONG+0 > 0)\n__acc_gnuc_extension__ typedef long long acc_llong_t;\n__acc_gnuc_extension__ typedef unsigned long long acc_ullong_t;\n#    endif\n#    if (!(ACC_SIZEOF_SHORT+0 > 0 && ACC_SIZEOF_INT+0 > 0 && ACC_SIZEOF_LONG+0 > 0))\n#        error \"missing defines for sizes\"\n#    endif\n#    if (!(ACC_SIZEOF_PTRDIFF_T+0 > 0 && ACC_SIZEOF_SIZE_T+0 > 0 && ACC_SIZEOF_VOID_P+0 > 0))\n#        error \"missing defines for sizes\"\n#    endif\n#    if !defined(acc_int16e_t)\n#        if (ACC_SIZEOF_LONG == 2)\n#            define acc_int16e_t          long\n#            define acc_uint16e_t         unsigned long\n#        elif (ACC_SIZEOF_INT == 2)\n#            define acc_int16e_t          int\n#            define acc_uint16e_t         unsigned int\n#        elif (ACC_SIZEOF_SHORT == 2)\n#            define acc_int16e_t          short int\n#            define acc_uint16e_t         unsigned short int\n#        elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_HI) && (ACC_CC_GNUC >= 0x025f00ul || ACC_CC_LLVM)\ntypedef int __acc_int16e_hi_t __attribute__ ((__mode__(__HI__)));\ntypedef unsigned int __acc_uint16e_hi_t __attribute__ ((__mode__(__HI__)));\n#            define acc_int16e_t          __acc_int16e_hi_t\n#            define acc_uint16e_t         __acc_uint16e_hi_t\n#        elif (ACC_SIZEOF___INT16 == 2)\n#            define acc_int16e_t          __int16\n#            define acc_uint16e_t         unsigned __int16\n#        else\n#        endif\n#    endif\n#    if defined(acc_int16e_t)\n#        define ACC_SIZEOF_ACC_INT16E_T   2\n#    endif\n#    if !defined(acc_int32e_t)\n#        if (ACC_SIZEOF_LONG == 4)\n#            define acc_int32e_t          long int\n#            define acc_uint32e_t         unsigned long int\n#        elif (ACC_SIZEOF_INT == 4)\n#            define acc_int32e_t          int\n#            define acc_uint32e_t         unsigned int\n#        elif (ACC_SIZEOF_SHORT == 4)\n#            define acc_int32e_t          short int\n#            define acc_uint32e_t         unsigned short int\n#        elif (ACC_SIZEOF_LONG_LONG == 4)\n#            define acc_int32e_t          acc_llong_t\n#            define acc_uint32e_t         acc_ullong_t\n#        elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_SI) && (ACC_CC_GNUC >= 0x025f00ul || ACC_CC_LLVM) && (__INT_MAX__+0 > 2147483647L)\ntypedef int __acc_int32e_si_t __attribute__ ((__mode__(__SI__)));\ntypedef unsigned int __acc_uint32e_si_t __attribute__ ((__mode__(__SI__)));\n#            define acc_int32e_t          __acc_int32e_si_t\n#            define acc_uint32e_t         __acc_uint32e_si_t\n#        elif 1 && !defined(ACC_CFG_TYPE_NO_MODE_SI) && (ACC_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L)\ntypedef int __acc_int32e_si_t __attribute__ ((__mode__(__SI__)));\ntypedef unsigned int __acc_uint32e_si_t __attribute__ ((__mode__(__SI__)));\n#            define acc_int32e_t          __acc_int32e_si_t\n#            define acc_uint32e_t         __acc_uint32e_si_t\n#            define ACC_INT32_C(c)        c##LL\n#            define ACC_UINT32_C(c)       c##ULL\n#        elif (ACC_SIZEOF___INT32 == 4)\n#            define acc_int32e_t          __int32\n#            define acc_uint32e_t         unsigned __int32\n#        else\n#        endif\n#    endif\n#    if defined(acc_int32e_t)\n#        define ACC_SIZEOF_ACC_INT32E_T   4\n#    endif\n#    if !defined(acc_int64e_t)\n#        if (ACC_SIZEOF___INT64 == 8)\n#            if (ACC_CC_BORLANDC) && !defined(ACC_CFG_TYPE_PREFER___INT64)\n#                define ACC_CFG_TYPE_PREFER___INT64 1\n#            endif\n#        endif\n#        if (ACC_SIZEOF_INT == 8) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)\n#            define acc_int64e_t          int\n#            define acc_uint64e_t         unsigned int\n#            define ACC_SIZEOF_ACC_INT64E_T   ACC_SIZEOF_INT\n#        elif (ACC_SIZEOF_LONG == 8)\n#            define acc_int64e_t          long int\n#            define acc_uint64e_t         unsigned long int\n#            define ACC_SIZEOF_ACC_INT64E_T   ACC_SIZEOF_LONG\n#        elif (ACC_SIZEOF_LONG_LONG == 8) && !defined(ACC_CFG_TYPE_PREFER___INT64)\n#            define acc_int64e_t          acc_llong_t\n#            define acc_uint64e_t         acc_ullong_t\n#            if (ACC_CC_BORLANDC)\n#                define ACC_INT64_C(c)      ((c) + 0ll)\n#                define ACC_UINT64_C(c)     ((c) + 0ull)\n#            else\n#                define ACC_INT64_C(c)      c##LL\n#                define ACC_UINT64_C(c)     c##ULL\n#            endif\n#            define ACC_SIZEOF_ACC_INT64E_T   ACC_SIZEOF_LONG_LONG\n#        elif (ACC_SIZEOF___INT64 == 8)\n#            define acc_int64e_t          __int64\n#            define acc_uint64e_t         unsigned __int64\n#            if (ACC_CC_BORLANDC)\n#                define ACC_INT64_C(c)      ((c) + 0i64)\n#                define ACC_UINT64_C(c)     ((c) + 0ui64)\n#            else\n#                define ACC_INT64_C(c)      c##i64\n#                define ACC_UINT64_C(c)     c##ui64\n#            endif\n#            define ACC_SIZEOF_ACC_INT64E_T   ACC_SIZEOF___INT64\n#        else\n#        endif\n#    endif\n#    if !defined(acc_int32l_t)\n#        if defined(acc_int32e_t)\n#            define acc_int32l_t          acc_int32e_t\n#            define acc_uint32l_t         acc_uint32e_t\n#            define ACC_SIZEOF_ACC_INT32L_T   ACC_SIZEOF_ACC_INT32E_T\n#        elif (ACC_SIZEOF_INT >= 4) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)\n#            define acc_int32l_t          int\n#            define acc_uint32l_t         unsigned int\n#            define ACC_SIZEOF_ACC_INT32L_T   ACC_SIZEOF_INT\n#        elif (ACC_SIZEOF_LONG >= 4)\n#            define acc_int32l_t          long int\n#            define acc_uint32l_t         unsigned long int\n#            define ACC_SIZEOF_ACC_INT32L_T   ACC_SIZEOF_LONG\n#        else\n#            error \"acc_int32l_t\"\n#        endif\n#    endif\n#    if !defined(acc_int64l_t)\n#        if defined(acc_int64e_t)\n#            define acc_int64l_t          acc_int64e_t\n#            define acc_uint64l_t         acc_uint64e_t\n#            define ACC_SIZEOF_ACC_INT64L_T   ACC_SIZEOF_ACC_INT64E_T\n#        else\n#        endif\n#    endif\n#    if !defined(acc_int32f_t)\n#        if (ACC_SIZEOF_SIZE_T >= 8)\n#            define acc_int32f_t          acc_int64l_t\n#            define acc_uint32f_t         acc_uint64l_t\n#            define ACC_SIZEOF_ACC_INT32F_T   ACC_SIZEOF_ACC_INT64L_T\n#        else\n#            define acc_int32f_t          acc_int32l_t\n#            define acc_uint32f_t         acc_uint32l_t\n#            define ACC_SIZEOF_ACC_INT32F_T   ACC_SIZEOF_ACC_INT32L_T\n#        endif\n#    endif\n#    if !defined(acc_intptr_t)\n#        if 1 && (ACC_OS_OS400 && (ACC_SIZEOF_VOID_P == 16))\n#            define __ACC_INTPTR_T_IS_POINTER 1\ntypedef char *acc_intptr_t;\ntypedef char *acc_uintptr_t;\n#            define acc_intptr_t          acc_intptr_t\n#            define acc_uintptr_t         acc_uintptr_t\n#            define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_VOID_P\n#        elif (ACC_CC_MSC && (_MSC_VER >= 1300) && (ACC_SIZEOF_VOID_P == 4) && (ACC_SIZEOF_INT == 4))\ntypedef __w64 int acc_intptr_t;\ntypedef __w64 unsigned int acc_uintptr_t;\n#            define acc_intptr_t          acc_intptr_t\n#            define acc_uintptr_t         acc_uintptr_t\n#            define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_INT\n#        elif (ACC_SIZEOF_SHORT == ACC_SIZEOF_VOID_P) && (ACC_SIZEOF_INT > ACC_SIZEOF_VOID_P)\n#            define acc_intptr_t          short\n#            define acc_uintptr_t         unsigned short\n#            define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_SHORT\n#        elif (ACC_SIZEOF_INT >= ACC_SIZEOF_VOID_P) && (ACC_SIZEOF_INT < ACC_SIZEOF_LONG)\n#            define acc_intptr_t          int\n#            define acc_uintptr_t         unsigned int\n#            define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_INT\n#        elif (ACC_SIZEOF_LONG >= ACC_SIZEOF_VOID_P)\n#            define acc_intptr_t          long\n#            define acc_uintptr_t         unsigned long\n#            define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_LONG\n#        elif (ACC_SIZEOF_ACC_INT64L_T >= ACC_SIZEOF_VOID_P)\n#            define acc_intptr_t          acc_int64l_t\n#            define acc_uintptr_t         acc_uint64l_t\n#            define ACC_SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_ACC_INT64L_T\n#        else\n#            error \"acc_intptr_t\"\n#        endif\n#    endif\n#    if !defined(acc_word_t)\n#        if defined(ACC_WORDSIZE) && (ACC_WORDSIZE > 0)\n#            if (ACC_WORDSIZE == ACC_SIZEOF_ACC_INTPTR_T) && !defined(__ACC_INTPTR_T_IS_POINTER)\n#                define acc_word_t            acc_uintptr_t\n#                define acc_sword_t           acc_intptr_t\n#                define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_INTPTR_T\n#            elif (ACC_WORDSIZE == ACC_SIZEOF_LONG)\n#                define acc_word_t            unsigned long\n#                define acc_sword_t           long\n#                define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_LONG\n#            elif (ACC_WORDSIZE == ACC_SIZEOF_INT)\n#                define acc_word_t            unsigned int\n#                define acc_sword_t           int\n#                define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_INT\n#            elif (ACC_WORDSIZE == ACC_SIZEOF_SHORT)\n#                define acc_word_t            unsigned short\n#                define acc_sword_t           short\n#                define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_SHORT\n#            elif (ACC_WORDSIZE == 1)\n#                define acc_word_t            unsigned char\n#                define acc_sword_t           signed char\n#                define ACC_SIZEOF_ACC_WORD_T 1\n#            elif (ACC_WORDSIZE == ACC_SIZEOF_ACC_INT64L_T)\n#                define acc_word_t            acc_uint64l_t\n#                define acc_sword_t           acc_int64l_t\n#                define ACC_SIZEOF_ACC_WORD_T ACC_SIZEOF_ACC_INT64L_T\n#            elif (ACC_ARCH_SPU) && (ACC_CC_GNUC)\n#                if 0\ntypedef unsigned acc_word_t __attribute__ ((__mode__(__V16QI__)));\ntypedef int acc_sword_t __attribute__ ((__mode__(__V16QI__)));\n#                    define acc_word_t            acc_word_t\n#                    define acc_sword_t           acc_sword_t\n#                    define ACC_SIZEOF_ACC_WORD_T 16\n#                endif\n#            else\n#                error \"acc_word_t\"\n#            endif\n#        endif\n#    endif\n#    if !defined(ACC_INT16_C)\n#        if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 2)\n#            define ACC_INT16_C(c)      ((c) + 0)\n#            define ACC_UINT16_C(c)     ((c) + 0U)\n#        elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 2)\n#            define ACC_INT16_C(c)      ((c) + 0L)\n#            define ACC_UINT16_C(c)     ((c) + 0UL)\n#        elif (ACC_SIZEOF_INT >= 2)\n#            define ACC_INT16_C(c)      c\n#            define ACC_UINT16_C(c)     c##U\n#        elif (ACC_SIZEOF_LONG >= 2)\n#            define ACC_INT16_C(c)      c##L\n#            define ACC_UINT16_C(c)     c##UL\n#        else\n#            error \"ACC_INT16_C\"\n#        endif\n#    endif\n#    if !defined(ACC_INT32_C)\n#        if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 4)\n#            define ACC_INT32_C(c)      ((c) + 0)\n#            define ACC_UINT32_C(c)     ((c) + 0U)\n#        elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 4)\n#            define ACC_INT32_C(c)      ((c) + 0L)\n#            define ACC_UINT32_C(c)     ((c) + 0UL)\n#        elif (ACC_SIZEOF_INT >= 4)\n#            define ACC_INT32_C(c)      c\n#            define ACC_UINT32_C(c)     c##U\n#        elif (ACC_SIZEOF_LONG >= 4)\n#            define ACC_INT32_C(c)      c##L\n#            define ACC_UINT32_C(c)     c##UL\n#        elif (ACC_SIZEOF_LONG_LONG >= 4)\n#            define ACC_INT32_C(c)      c##LL\n#            define ACC_UINT32_C(c)     c##ULL\n#        else\n#            error \"ACC_INT32_C\"\n#        endif\n#    endif\n#    if !defined(ACC_INT64_C) && defined(acc_int64l_t)\n#        if (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_INT >= 8)\n#            define ACC_INT64_C(c)      ((c) + 0)\n#            define ACC_UINT64_C(c)     ((c) + 0U)\n#        elif (ACC_BROKEN_INTEGRAL_CONSTANTS) && (ACC_SIZEOF_LONG >= 8)\n#            define ACC_INT64_C(c)      ((c) + 0L)\n#            define ACC_UINT64_C(c)     ((c) + 0UL)\n#        elif (ACC_SIZEOF_INT >= 8)\n#            define ACC_INT64_C(c)      c\n#            define ACC_UINT64_C(c)     c##U\n#        elif (ACC_SIZEOF_LONG >= 8)\n#            define ACC_INT64_C(c)      c##L\n#            define ACC_UINT64_C(c)     c##UL\n#        else\n#            error \"ACC_INT64_C\"\n#        endif\n#    endif\n#    if !defined(SIZEOF_ACC_INT16E_T) && defined(ACC_SIZEOF_ACC_INT16E_T)\n#        define SIZEOF_ACC_INT16E_T   ACC_SIZEOF_ACC_INT16E_T\n#    endif\n#    if !defined(SIZEOF_ACC_INT32E_T) && defined(ACC_SIZEOF_ACC_INT32E_T)\n#        define SIZEOF_ACC_INT32E_T   ACC_SIZEOF_ACC_INT32E_T\n#    endif\n#    if !defined(SIZEOF_ACC_INT64E_T) && defined(ACC_SIZEOF_ACC_INT64E_T)\n#        define SIZEOF_ACC_INT64E_T   ACC_SIZEOF_ACC_INT64E_T\n#    endif\n#    if !defined(SIZEOF_ACC_INT32L_T) && defined(ACC_SIZEOF_ACC_INT32L_T)\n#        define SIZEOF_ACC_INT32L_T   ACC_SIZEOF_ACC_INT32L_T\n#    endif\n#    if !defined(SIZEOF_ACC_INT64L_T) && defined(ACC_SIZEOF_ACC_INT64L_T)\n#        define SIZEOF_ACC_INT64L_T   ACC_SIZEOF_ACC_INT64L_T\n#    endif\n#    if !defined(SIZEOF_ACC_INT32F_T) && defined(ACC_SIZEOF_ACC_INT32F_T)\n#        define SIZEOF_ACC_INT32F_T   ACC_SIZEOF_ACC_INT32F_T\n#    endif\n#    if !defined(SIZEOF_ACC_INTPTR_T) && defined(ACC_SIZEOF_ACC_INTPTR_T)\n#        define SIZEOF_ACC_INTPTR_T   ACC_SIZEOF_ACC_INTPTR_T\n#    endif\n#    if !defined(SIZEOF_ACC_WORD_T) && defined(ACC_SIZEOF_ACC_WORD_T)\n#        define SIZEOF_ACC_WORD_T     ACC_SIZEOF_ACC_WORD_T\n#    endif\n#    if 1 && !defined(acc_signo_t) && defined(__linux__) && defined(__dietlibc__) && (ACC_SIZEOF_INT != 4)\n#        define acc_signo_t           acc_int32e_t\n#    endif\n#    if !defined(acc_signo_t)\n#        define acc_signo_t           int\n#    endif\n#    if defined(__cplusplus)\nextern \"C\" {\n#    endif\n#    if (ACC_BROKEN_CDECL_ALT_SYNTAX)\n\ttypedef void __acc_cdecl_sighandler(*acc_sighandler_t) (acc_signo_t);\n#    elif defined(RETSIGTYPE)\n\ttypedef RETSIGTYPE(__acc_cdecl_sighandler * acc_sighandler_t) (acc_signo_t);\n#    else\n\ttypedef void (__acc_cdecl_sighandler * acc_sighandler_t) (acc_signo_t);\n#    endif\n#    if defined(__cplusplus)\n}\n#    endif\n#    if !defined(ACC_CFG_NO_ACC_UA_H)\n#        if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020700ul))\n#        elif (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020800ul)) && defined(__cplusplus)\n#        elif (ACC_CC_INTELC) && defined(_WIN32)\n#        elif (ACC_CC_INTELC && (__INTEL_COMPILER < 700))\n#        elif (ACC_CC_LLVM)\n#        elif (ACC_CC_GNUC || ACC_CC_INTELC || ACC_CC_PATHSCALE)\n#            if !defined(__acc_ua16_t) && (ACC_OPT_UNALIGNED16) && defined(acc_int16e_t)\ntypedef struct {\n\t__acc_ua_volatile acc_uint16e_t v __attribute__ ((__packed__));\n} __acc_ua16_t;\n#                define __acc_ua16_t __acc_ua16_t\n#            endif\n#            if !defined(__acc_ua32_t) && (ACC_OPT_UNALIGNED32) && defined(acc_int32e_t)\ntypedef struct {\n\t__acc_ua_volatile acc_uint32e_t v __attribute__ ((__packed__));\n} __acc_ua32_t;\n#                define __acc_ua32_t __acc_ua32_t\n#            endif\n#            if !defined(__acc_ua64_t) && (ACC_OPT_UNALIGNED64) && defined(acc_int64l_t)\ntypedef struct {\n\t__acc_ua_volatile acc_uint64l_t v __attribute__ ((__packed__));\n} __acc_ua64_t;\n#                define __acc_ua64_t __acc_ua64_t\n#            endif\n#        endif\n#        if (ACC_OPT_UNALIGNED16) && defined(acc_int16e_t)\n#            define ACC_UA_GET16(p)         (* (__acc_ua_volatile const acc_uint16e_t*) (__acc_ua_volatile const void*) (p))\n#            define ACC_UA_SET16(p,v)       (* (__acc_ua_volatile acc_uint16e_t*) (__acc_ua_volatile void*) (p) = (acc_uint16e_t) (v))\n#            if (ACC_ABI_BIG_ENDIAN)\n#                define ACC_UA_GET_BE16(p)    ACC_UA_GET16(p)\n#                define ACC_UA_SET_BE16(p,v)  ACC_UA_SET16(p,v)\n#            elif (ACC_ABI_LITTLE_ENDIAN)\n#                define ACC_UA_GET_LE16(p)    ACC_UA_GET16(p)\n#                define ACC_UA_SET_LE16(p,v)  ACC_UA_SET16(p,v)\n#            endif\n#            if !defined(ACC_CFG_NO_INLINE_ASM) && defined(__acc_HAVE_forceinline)\n#                if (ACC_ARCH_POWERPC && ACC_ABI_BIG_ENDIAN) && (ACC_CC_GNUC)\n#                    if !defined(ACC_UA_GET_LE16)\nextern __acc_forceinline unsigned long __ACC_UA_GET_LE16(__acc_ua_volatile const void *pp);\nextern __acc_forceinline unsigned long __ACC_UA_GET_LE16(__acc_ua_volatile const void *pp) {\n\t__acc_ua_volatile const acc_uint16e_t *p = (__acc_ua_volatile const acc_uint16e_t *)pp;\n\tunsigned long v;\n\t__asm__ __volatile__(\"lhbrx %0,0,%1\":\"=r\"(v):\"r\"(p), \"m\"(*p));\n\treturn v;\n}\n\n#                        define ACC_UA_GET_LE16(p)      __ACC_UA_GET_LE16(p)\n#                    endif\n#                    if !defined(ACC_UA_SET_LE16)\nextern __acc_forceinline void __ACC_UA_SET_LE16(__acc_ua_volatile void *pp, unsigned long v);\nextern __acc_forceinline void __ACC_UA_SET_LE16(__acc_ua_volatile void *pp, unsigned long v) {\n\t__acc_ua_volatile acc_uint16e_t *p = (__acc_ua_volatile acc_uint16e_t *) pp;\n\t__asm__ __volatile__(\"sthbrx %2,0,%1\":\"=m\"(*p):\"r\"(p), \"r\"(v));\n}\n\n#                        define ACC_UA_SET_LE16(p,v)    __ACC_UA_SET_LE16(p,v)\n#                    endif\n#                endif\n#            endif\n#            if !defined(ACC_UA_COPY16)\n#                define ACC_UA_COPY16(d,s)    ACC_UA_SET16(d, ACC_UA_GET16(s))\n#            endif\n#        endif\n#        if (ACC_OPT_UNALIGNED32) && defined(acc_int32e_t)\n#            define ACC_UA_GET32(p)         (* (__acc_ua_volatile const acc_uint32e_t*) (__acc_ua_volatile const void*) (p))\n#            define ACC_UA_SET32(p,v)       (* (__acc_ua_volatile acc_uint32e_t*) (__acc_ua_volatile void*) (p) = (acc_uint32e_t) (v))\n#            if (ACC_ABI_BIG_ENDIAN)\n#                define ACC_UA_GET_BE32(p)    ACC_UA_GET32(p)\n#                define ACC_UA_SET_BE32(p,v)  ACC_UA_SET32(p,v)\n#            elif (ACC_ABI_LITTLE_ENDIAN)\n#                define ACC_UA_GET_LE32(p)    ACC_UA_GET32(p)\n#                define ACC_UA_SET_LE32(p,v)  ACC_UA_SET32(p,v)\n#            endif\n#            if !defined(ACC_CFG_NO_INLINE_ASM) && defined(__acc_HAVE_forceinline)\n#                if (ACC_ARCH_POWERPC && ACC_ABI_BIG_ENDIAN) && (ACC_CC_GNUC)\n#                    if !defined(ACC_UA_GET_LE32)\nextern __acc_forceinline unsigned long __ACC_UA_GET_LE32(__acc_ua_volatile const void *pp);\nextern __acc_forceinline unsigned long __ACC_UA_GET_LE32(__acc_ua_volatile const void *pp) {\n\t__acc_ua_volatile const acc_uint32e_t *p = (__acc_ua_volatile const acc_uint32e_t *)pp;\n\tunsigned long v;\n\t__asm__ __volatile__(\"lwbrx %0,0,%1\":\"=r\"(v):\"r\"(p), \"m\"(*p));\n\treturn v;\n}\n\n#                        define ACC_UA_GET_LE32(p)      __ACC_UA_GET_LE32(p)\n#                    endif\n#                    if !defined(ACC_UA_SET_LE32)\nextern __acc_forceinline void __ACC_UA_SET_LE32(__acc_ua_volatile void *pp, unsigned long v);\nextern __acc_forceinline void __ACC_UA_SET_LE32(__acc_ua_volatile void *pp, unsigned long v) {\n\t__acc_ua_volatile acc_uint32e_t *p = (__acc_ua_volatile acc_uint32e_t *) pp;\n\t__asm__ __volatile__(\"stwbrx %2,0,%1\":\"=m\"(*p):\"r\"(p), \"r\"(v));\n}\n\n#                        define ACC_UA_SET_LE32(p,v)    __ACC_UA_SET_LE32(p,v)\n#                    endif\n#                endif\n#            endif\n#            if !defined(ACC_UA_COPY32)\n#                define ACC_UA_COPY32(d,s)    ACC_UA_SET32(d, ACC_UA_GET32(s))\n#            endif\n#        endif\n#        if (ACC_OPT_UNALIGNED64) && defined(acc_int64l_t)\n#            define ACC_UA_GET64(p)         (* (__acc_ua_volatile const acc_uint64l_t*) (__acc_ua_volatile const void*) (p))\n#            define ACC_UA_SET64(p,v)       (* (__acc_ua_volatile acc_uint64l_t*) (__acc_ua_volatile void*) (p) = (acc_uint64l_t) (v))\n#            if (ACC_ABI_BIG_ENDIAN)\n#                define ACC_UA_GET_BE64(p)    ACC_UA_GET64(p)\n#                define ACC_UA_SET_BE64(p,v)  ACC_UA_SET64(p,v)\n#            elif (ACC_ABI_LITTLE_ENDIAN)\n#                define ACC_UA_GET_LE64(p)    ACC_UA_GET64(p)\n#                define ACC_UA_SET_LE64(p,v)  ACC_UA_SET64(p,v)\n#            endif\n#            if !defined(ACC_UA_COPY64)\n#                define ACC_UA_COPY64(d,s)    ACC_UA_SET64(d, ACC_UA_GET64(s))\n#            endif\n#        endif\n#    endif\n#endif\n#if defined(ACC_WANT_ACC_INCD_H)\n#    undef ACC_WANT_ACC_INCD_H\n#    ifndef __ACC_INCD_H_INCLUDED\n#        define __ACC_INCD_H_INCLUDED 1\n#        if defined(ACC_LIBC_NAKED)\n#            ifndef __ACC_FALLBACK_STDDEF_H_INCLUDED\n#                define __ACC_FALLBACK_STDDEF_H_INCLUDED\n#                if defined(__PTRDIFF_TYPE__)\ntypedef __PTRDIFF_TYPE__ acc_fallback_ptrdiff_t;\n#                elif defined(__MIPS_PSX2__)\ntypedef int acc_fallback_ptrdiff_t;\n#                else\ntypedef long acc_fallback_ptrdiff_t;\n#                endif\n#                if defined(__SIZE_TYPE__)\ntypedef __SIZE_TYPE__ acc_fallback_size_t;\n#                elif defined(__MIPS_PSX2__)\ntypedef unsigned int acc_fallback_size_t;\n#                else\ntypedef unsigned long acc_fallback_size_t;\n#                endif\n#                if !defined(ptrdiff_t)\ntypedef acc_fallback_ptrdiff_t ptrdiff_t;\n#                    ifndef _PTRDIFF_T_DEFINED\n#                        define _PTRDIFF_T_DEFINED 1\n#                    endif\n#                endif\n#                if !defined(size_t)\ntypedef acc_fallback_size_t size_t;\n#                    ifndef _SIZE_T_DEFINED\n#                        define _SIZE_T_DEFINED 1\n#                    endif\n#                endif\n#                if !defined(__cplusplus) && !defined(wchar_t)\ntypedef unsigned short wchar_t;\n#                    ifndef _WCHAR_T_DEFINED\n#                        define _WCHAR_T_DEFINED 1\n#                    endif\n#                endif\n#                ifndef NULL\n#                    if defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ >= 4)\n#                        define NULL    __null\n#                    elif defined(__cplusplus)\n#                        define NULL    0\n#                    else\n#                        define NULL    ((void*)0)\n#                    endif\n#                endif\n#                ifndef offsetof\n#                    define offsetof(s,m)   ((size_t)((ptrdiff_t)&(((s*)0)->m)))\n#                endif\n#            endif\n#        elif defined(ACC_LIBC_FREESTANDING)\n#            if HAVE_STDDEF_H\n#                include <stddef.h>\n#            endif\n#            if HAVE_STDINT_H\n#                include <stdint.h>\n#            endif\n#        elif defined(ACC_LIBC_MOSTLY_FREESTANDING)\n#            if HAVE_STDIO_H\n#                include <stdio.h>\n#            endif\n#            if HAVE_STDDEF_H\n#                include <stddef.h>\n#            endif\n#            if HAVE_STDINT_H\n#                include <stdint.h>\n#            endif\n#        else\n#            include <stdio.h>\n#            if defined(HAVE_TIME_H) && defined(__MSL__) && defined(__cplusplus)\n#                include <time.h>\n#            endif\n#            if HAVE_SYS_TYPES_H\n#                include <sys/types.h>\n#            endif\n#            if HAVE_SYS_STAT_H\n#                include <sys/stat.h>\n#            endif\n#            if STDC_HEADERS\n#                include <stdlib.h>\n#                include <stddef.h>\n#            else\n#                if HAVE_STDLIB_H\n#                    include <stdlib.h>\n#                endif\n#            endif\n#            if HAVE_STRING_H\n#                if !STDC_HEADERS && HAVE_MEMORY_H\n#                    include <memory.h>\n#                endif\n#                include <string.h>\n#            endif\n#            if HAVE_STRINGS_H\n#                include <strings.h>\n#            endif\n#            if HAVE_INTTYPES_H\n#                include <inttypes.h>\n#            else\n#                if HAVE_STDINT_H\n#                    include <stdint.h>\n#                endif\n#            endif\n#            if HAVE_UNISTD_H\n#                include <unistd.h>\n#            endif\n#        endif\n#    endif\n#endif\n#if defined(ACC_WANT_ACC_INCE_H)\n#    undef ACC_WANT_ACC_INCE_H\n#    ifndef __ACC_INCE_H_INCLUDED\n#        define __ACC_INCE_H_INCLUDED 1\n#        if defined(ACC_LIBC_NAKED)\n#        elif defined(ACC_LIBC_FREESTANDING)\n#        elif defined(ACC_LIBC_MOSTLY_FREESTANDING)\n#            if defined(HAVE_SETJMP_H)\n#                include <setjmp.h>\n#            endif\n#        else\n#            if defined(HAVE_STDARG_H)\n#                include <stdarg.h>\n#            endif\n#            if defined(HAVE_CTYPE_H)\n#                include <ctype.h>\n#            endif\n#            if defined(HAVE_ERRNO_H)\n#                include <errno.h>\n#            endif\n#            if defined(HAVE_MALLOC_H)\n#                include <malloc.h>\n#            endif\n#            if defined(HAVE_ALLOCA_H)\n#                include <alloca.h>\n#            endif\n#            if defined(HAVE_FCNTL_H)\n#                include <fcntl.h>\n#            endif\n#            if defined(HAVE_DIRENT_H)\n#                include <dirent.h>\n#            endif\n#            if defined(HAVE_SETJMP_H)\n#                include <setjmp.h>\n#            endif\n#            if defined(HAVE_SIGNAL_H)\n#                include <signal.h>\n#            endif\n#            if defined(TIME_WITH_SYS_TIME)\n#                include <sys/time.h>\n#                include <time.h>\n#            elif defined(HAVE_TIME_H)\n#                include <time.h>\n#            endif\n#            if defined(HAVE_UTIME_H)\n#                include <utime.h>\n#            elif defined(HAVE_SYS_UTIME_H)\n#                include <sys/utime.h>\n#            endif\n#            if defined(HAVE_IO_H)\n#                include <io.h>\n#            endif\n#            if defined(HAVE_DOS_H)\n#                include <dos.h>\n#            endif\n#            if defined(HAVE_DIRECT_H)\n#                include <direct.h>\n#            endif\n#            if defined(HAVE_SHARE_H)\n#                include <share.h>\n#            endif\n#            if defined(ACC_CC_NDPC)\n#                include <os.h>\n#            endif\n#            if defined(__TOS__) && (defined(__PUREC__) || defined(__TURBOC__))\n#                include <ext.h>\n#            endif\n#        endif\n#    endif\n#endif\n#if defined(ACC_WANT_ACC_INCI_H)\n#    undef ACC_WANT_ACC_INCI_H\n#    ifndef __ACC_INCI_H_INCLUDED\n#        define __ACC_INCI_H_INCLUDED 1\n#        if defined(ACC_LIBC_NAKED)\n#        elif defined(ACC_LIBC_FREESTANDING)\n#        elif defined(ACC_LIBC_MOSTLY_FREESTANDING)\n#        else\n#            if (ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))\n#                include <tos.h>\n#            elif (ACC_HAVE_WINDOWS_H)\n#                if 1 && !defined(WIN32_LEAN_AND_MEAN)\n#                    define WIN32_LEAN_AND_MEAN 1\n#                endif\n#                if 1 && !defined(_WIN32_WINNT)\n#                    define _WIN32_WINNT 0x0400\n#                endif\n#                include <windows.h>\n#                if (ACC_CC_BORLANDC || ACC_CC_TURBOC)\n#                    include <dir.h>\n#                endif\n#            elif (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_WIN16)\n#                if (ACC_CC_AZTECC)\n#                    include <model.h>\n#                    include <stat.h>\n#                elif (ACC_CC_BORLANDC || ACC_CC_TURBOC)\n#                    include <alloc.h>\n#                    include <dir.h>\n#                elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n#                    include <sys/exceptn.h>\n#                elif (ACC_CC_PACIFICC)\n#                    include <unixio.h>\n#                    include <stat.h>\n#                    include <sys.h>\n#                elif (ACC_CC_WATCOMC)\n#                    include <i86.h>\n#                endif\n#            elif (ACC_OS_OS216)\n#                if (ACC_CC_WATCOMC)\n#                    include <i86.h>\n#                endif\n#            endif\n#            if defined(HAVE_SYS_MMAN_H)\n#                include <sys/mman.h>\n#            endif\n#            if defined(HAVE_SYS_RESOURCE_H)\n#                include <sys/resource.h>\n#            endif\n#            if (ACC_OS_DOS16 || ACC_OS_OS216 || ACC_OS_WIN16)\n#                if defined(FP_OFF)\n#                    define ACC_PTR_FP_OFF(x)   FP_OFF(x)\n#                elif defined(_FP_OFF)\n#                    define ACC_PTR_FP_OFF(x)   _FP_OFF(x)\n#                else\n#                    define ACC_PTR_FP_OFF(x)   (((const unsigned __far*)&(x))[0])\n#                endif\n#                if defined(FP_SEG)\n#                    define ACC_PTR_FP_SEG(x)   FP_SEG(x)\n#                elif defined(_FP_SEG)\n#                    define ACC_PTR_FP_SEG(x)   _FP_SEG(x)\n#                else\n#                    define ACC_PTR_FP_SEG(x)   (((const unsigned __far*)&(x))[1])\n#                endif\n#                if defined(MK_FP)\n#                    define ACC_PTR_MK_FP(s,o)  MK_FP(s,o)\n#                elif defined(_MK_FP)\n#                    define ACC_PTR_MK_FP(s,o)  _MK_FP(s,o)\n#                else\n#                    define ACC_PTR_MK_FP(s,o)  ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o)))\n#                endif\n#                if 0\n#                    undef ACC_PTR_FP_OFF\n#                    undef ACC_PTR_FP_SEG\n#                    undef ACC_PTR_MK_FP\n#                    define ACC_PTR_FP_OFF(x)   (((const unsigned __far*)&(x))[0])\n#                    define ACC_PTR_FP_SEG(x)   (((const unsigned __far*)&(x))[1])\n#                    define ACC_PTR_MK_FP(s,o)  ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o)))\n#                endif\n#            endif\n#        endif\n#    endif\n#endif\n#if defined(ACC_WANT_ACC_LIB_H)\n#    undef ACC_WANT_ACC_LIB_H\n#    ifndef __ACC_LIB_H_INCLUDED\n#        define __ACC_LIB_H_INCLUDED 1\n#        if !defined(__ACCLIB_FUNCNAME)\n#            define __ACCLIB_FUNCNAME(f)  f\n#        endif\n#        if !defined(ACCLIB_EXTERN)\n#            define ACCLIB_EXTERN(r,f)                extern r __ACCLIB_FUNCNAME(f)\n#        endif\n#        if !defined(ACCLIB_EXTERN_NOINLINE)\n#            if defined(__acc_noinline)\n#                define ACCLIB_EXTERN_NOINLINE(r,f)     extern __acc_noinline r __ACCLIB_FUNCNAME(f)\n#            else\n#                define ACCLIB_EXTERN_NOINLINE(r,f)     extern r __ACCLIB_FUNCNAME(f)\n#            endif\n#        endif\n#        if !defined(__ACCLIB_CONST_CAST_RETURN)\n#            if 1 && (ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#                define __ACCLIB_CONST_CAST_RETURN(type,var) return (type) (acc_uintptr_t) (var);\n#            elif (ACC_CC_GNUC || ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#                define __ACCLIB_CONST_CAST_RETURN(type,var) \\\n        { union { type a; const type b; } u; u.b = (var); return u.a; }\n#            else\n#                define __ACCLIB_CONST_CAST_RETURN(type,var) return (type) (var);\n#            endif\n#        endif\n#        if (ACC_OS_WIN64)\n#            define acclib_handle_t       acc_int64l_t\n#            define acclib_uhandle_t      acc_uint64l_t\n#        elif (ACC_ARCH_I386 && ACC_CC_MSC && (_MSC_VER >= 1300))\ntypedef __w64 long acclib_handle_t;\ntypedef __w64 unsigned long acclib_uhandle_t;\n#            define acclib_handle_t       acclib_handle_t\n#            define acclib_uhandle_t      acclib_uhandle_t\n#        else\n#            define acclib_handle_t       long\n#            define acclib_uhandle_t      unsigned long\n#        endif\n#        if 0\nACCLIB_EXTERN(int, acc_ascii_digit) (int);\nACCLIB_EXTERN(int, acc_ascii_islower) (int);\nACCLIB_EXTERN(int, acc_ascii_isupper) (int);\nACCLIB_EXTERN(int, acc_ascii_tolower) (int);\nACCLIB_EXTERN(int, acc_ascii_toupper) (int);\nACCLIB_EXTERN(int, acc_ascii_utolower) (int);\nACCLIB_EXTERN(int, acc_ascii_utoupper) (int);\n#        endif\n#        define acc_ascii_isdigit(c)    (((unsigned)(c) - 48) < 10)\n#        define acc_ascii_islower(c)    (((unsigned)(c) - 97) < 26)\n#        define acc_ascii_isupper(c)    (((unsigned)(c) - 65) < 26)\n#        define acc_ascii_tolower(c)    ((int)(c) + (acc_ascii_isupper(c) << 5))\n#        define acc_ascii_toupper(c)    ((int)(c) - (acc_ascii_islower(c) << 5))\n#        define acc_ascii_utolower(c)   acc_ascii_tolower((unsigned char)(c))\n#        define acc_ascii_utoupper(c)   acc_ascii_toupper((unsigned char)(c))\n#        ifndef acc_hsize_t\n#            if (ACC_HAVE_MM_HUGE_PTR)\n#                define acc_hsize_t   unsigned long\n#                define acc_hvoid_p   void __huge *\n#                define acc_hchar_p   char __huge *\n#                define acc_hchar_pp  char __huge * __huge *\n#                define acc_hbyte_p   unsigned char __huge *\n#            else\n#                define acc_hsize_t   size_t\n#                define acc_hvoid_p   void *\n#                define acc_hchar_p   char *\n#                define acc_hchar_pp  char **\n#                define acc_hbyte_p   unsigned char *\n#            endif\n#        endif\nACCLIB_EXTERN(acc_hvoid_p, acc_halloc) (acc_hsize_t);\nACCLIB_EXTERN(void, acc_hfree) (acc_hvoid_p);\n#        if (ACC_OS_DOS16 || ACC_OS_OS216)\nACCLIB_EXTERN(void __far *, acc_dos_alloc) (unsigned long);\nACCLIB_EXTERN(int, acc_dos_free) (void __far *);\n#        endif\nACCLIB_EXTERN(int, acc_hmemcmp) (const acc_hvoid_p, const acc_hvoid_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hvoid_p, acc_hmemcpy) (acc_hvoid_p, const acc_hvoid_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hvoid_p, acc_hmemmove) (acc_hvoid_p, const acc_hvoid_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hvoid_p, acc_hmemset) (acc_hvoid_p, int, acc_hsize_t);\nACCLIB_EXTERN(acc_hsize_t, acc_hstrlen) (const acc_hchar_p);\nACCLIB_EXTERN(int, acc_hstrcmp) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(int, acc_hstrncmp) (const acc_hchar_p, const acc_hchar_p, acc_hsize_t);\nACCLIB_EXTERN(int, acc_ascii_hstricmp) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(int, acc_ascii_hstrnicmp) (const acc_hchar_p, const acc_hchar_p, acc_hsize_t);\nACCLIB_EXTERN(int, acc_ascii_hmemicmp) (const acc_hvoid_p, const acc_hvoid_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrstr) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstristr) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hvoid_p, acc_hmemmem) (const acc_hvoid_p, acc_hsize_t, const acc_hvoid_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemimem) (const acc_hvoid_p, acc_hsize_t, const acc_hvoid_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrcpy) (acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrcat) (acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hsize_t, acc_hstrlcpy) (acc_hchar_p, const acc_hchar_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hsize_t, acc_hstrlcat) (acc_hchar_p, const acc_hchar_p, acc_hsize_t);\nACCLIB_EXTERN(int, acc_hstrscpy) (acc_hchar_p, const acc_hchar_p, acc_hsize_t);\nACCLIB_EXTERN(int, acc_hstrscat) (acc_hchar_p, const acc_hchar_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrccpy) (acc_hchar_p, const acc_hchar_p, int);\nACCLIB_EXTERN(acc_hvoid_p, acc_hmemccpy) (acc_hvoid_p, const acc_hvoid_p, int, acc_hsize_t);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrchr) (const acc_hchar_p, int);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrrchr) (const acc_hchar_p, int);\nACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstrichr) (const acc_hchar_p, int);\nACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstrrichr) (const acc_hchar_p, int);\nACCLIB_EXTERN(acc_hvoid_p, acc_hmemchr) (const acc_hvoid_p, int, acc_hsize_t);\nACCLIB_EXTERN(acc_hvoid_p, acc_hmemrchr) (const acc_hvoid_p, int, acc_hsize_t);\nACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemichr) (const acc_hvoid_p, int, acc_hsize_t);\nACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemrichr) (const acc_hvoid_p, int, acc_hsize_t);\nACCLIB_EXTERN(acc_hsize_t, acc_hstrspn) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hsize_t, acc_hstrrspn) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hsize_t, acc_hstrcspn) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hsize_t, acc_hstrrcspn) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrpbrk) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrrpbrk) (const acc_hchar_p, const acc_hchar_p);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrsep) (acc_hchar_pp, const acc_hchar_p);\nACCLIB_EXTERN(acc_hchar_p, acc_hstrrsep) (acc_hchar_pp, const acc_hchar_p);\nACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstrlwr) (acc_hchar_p);\nACCLIB_EXTERN(acc_hchar_p, acc_ascii_hstrupr) (acc_hchar_p);\nACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemlwr) (acc_hvoid_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hvoid_p, acc_ascii_hmemupr) (acc_hvoid_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hsize_t, acc_hfread) (void *, acc_hvoid_p, acc_hsize_t);\nACCLIB_EXTERN(acc_hsize_t, acc_hfwrite) (void *, const acc_hvoid_p, acc_hsize_t);\n#        if (ACC_HAVE_MM_HUGE_PTR)\nACCLIB_EXTERN(long, acc_hread) (int, acc_hvoid_p, long);\nACCLIB_EXTERN(long, acc_hwrite) (int, const acc_hvoid_p, long);\n#        endif\nACCLIB_EXTERN(long, acc_safe_hread) (int, acc_hvoid_p, long);\nACCLIB_EXTERN(long, acc_safe_hwrite) (int, const acc_hvoid_p, long);\nACCLIB_EXTERN(unsigned, acc_ua_get_be16) (const acc_hvoid_p);\nACCLIB_EXTERN(acc_uint32l_t, acc_ua_get_be24) (const acc_hvoid_p);\nACCLIB_EXTERN(acc_uint32l_t, acc_ua_get_be32) (const acc_hvoid_p);\nACCLIB_EXTERN(void, acc_ua_set_be16) (acc_hvoid_p, unsigned);\nACCLIB_EXTERN(void, acc_ua_set_be24) (acc_hvoid_p, acc_uint32l_t);\nACCLIB_EXTERN(void, acc_ua_set_be32) (acc_hvoid_p, acc_uint32l_t);\nACCLIB_EXTERN(unsigned, acc_ua_get_le16) (const acc_hvoid_p);\nACCLIB_EXTERN(acc_uint32l_t, acc_ua_get_le24) (const acc_hvoid_p);\nACCLIB_EXTERN(acc_uint32l_t, acc_ua_get_le32) (const acc_hvoid_p);\nACCLIB_EXTERN(void, acc_ua_set_le16) (acc_hvoid_p, unsigned);\nACCLIB_EXTERN(void, acc_ua_set_le24) (acc_hvoid_p, acc_uint32l_t);\nACCLIB_EXTERN(void, acc_ua_set_le32) (acc_hvoid_p, acc_uint32l_t);\n#        if defined(acc_int64l_t)\nACCLIB_EXTERN(acc_uint64l_t, acc_ua_get_be64) (const acc_hvoid_p);\nACCLIB_EXTERN(void, acc_ua_set_be64) (acc_hvoid_p, acc_uint64l_t);\nACCLIB_EXTERN(acc_uint64l_t, acc_ua_get_le64) (const acc_hvoid_p);\nACCLIB_EXTERN(void, acc_ua_set_le64) (acc_hvoid_p, acc_uint64l_t);\n#        endif\nACCLIB_EXTERN_NOINLINE(short, acc_vget_short) (short, int);\nACCLIB_EXTERN_NOINLINE(int, acc_vget_int) (int, int);\nACCLIB_EXTERN_NOINLINE(long, acc_vget_long) (long, int);\n#        if defined(acc_int64l_t)\nACCLIB_EXTERN_NOINLINE(acc_int64l_t, acc_vget_acc_int64l_t) (acc_int64l_t, int);\n#        endif\nACCLIB_EXTERN_NOINLINE(acc_hsize_t, acc_vget_acc_hsize_t) (acc_hsize_t, int);\n#        if !defined(ACC_CFG_NO_FLOAT)\nACCLIB_EXTERN_NOINLINE(float, acc_vget_float) (float, int);\n#        endif\n#        if !defined(ACC_CFG_NO_DOUBLE)\nACCLIB_EXTERN_NOINLINE(double, acc_vget_double) (double, int);\n#        endif\nACCLIB_EXTERN_NOINLINE(acc_hvoid_p, acc_vget_acc_hvoid_p) (acc_hvoid_p, int);\nACCLIB_EXTERN_NOINLINE(const acc_hvoid_p, acc_vget_acc_hvoid_cp) (const acc_hvoid_p, int);\n#        if !defined(ACC_FN_PATH_MAX)\n#            if (ACC_OS_DOS16 || ACC_OS_WIN16)\n#                define ACC_FN_PATH_MAX   143\n#            elif (ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN32 || ACC_OS_WIN64)\n#                define ACC_FN_PATH_MAX   259\n#            elif (ACC_OS_TOS)\n#                define ACC_FN_PATH_MAX   259\n#            endif\n#        endif\n#        if !defined(ACC_FN_PATH_MAX)\n#            define ACC_FN_PATH_MAX   1023\n#        endif\n#        if !defined(ACC_FN_NAME_MAX)\n#            if (ACC_OS_DOS16 || ACC_OS_WIN16)\n#                define ACC_FN_NAME_MAX   12\n#            elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))\n#                define ACC_FN_NAME_MAX   12\n#            elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n#            elif (ACC_OS_DOS32)\n#                define ACC_FN_NAME_MAX   12\n#            endif\n#        endif\n#        if !defined(ACC_FN_NAME_MAX)\n#            define ACC_FN_NAME_MAX   ACC_FN_PATH_MAX\n#        endif\n#        define ACC_FNMATCH_NOESCAPE        1\n#        define ACC_FNMATCH_PATHNAME        2\n#        define ACC_FNMATCH_PATHSTAR        4\n#        define ACC_FNMATCH_PERIOD          8\n#        define ACC_FNMATCH_ASCII_CASEFOLD  16\nACCLIB_EXTERN(int, acc_fnmatch) (const acc_hchar_p, const acc_hchar_p, int);\n#        undef __ACCLIB_USE_OPENDIR\n#        if (HAVE_DIRENT_H || ACC_CC_WATCOMC)\n#            define __ACCLIB_USE_OPENDIR 1\n#            if (ACC_OS_DOS32 && defined(__BORLANDC__))\n#            elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n#            elif (ACC_OS_OS2 || ACC_OS_OS216)\n#            elif (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC)\n#            elif (ACC_OS_WIN32 && !defined(ACC_HAVE_WINDOWS_H))\n#            elif (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_TOS || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)\n#                undef __ACCLIB_USE_OPENDIR\n#            endif\n#        endif\ntypedef struct {\n#        if defined(__ACCLIB_USE_OPENDIR)\n\tvoid *u_dirp;\n#            if (ACC_CC_WATCOMC)\n\tunsigned short f_time;\n\tunsigned short f_date;\n\tunsigned long f_size;\n#            endif\n\tchar f_name[ACC_FN_NAME_MAX + 1];\n#        elif (ACC_OS_WIN32 || ACC_OS_WIN64)\n\tacclib_handle_t u_handle;\n\tunsigned f_attr;\n\tunsigned f_size_low;\n\tunsigned f_size_high;\n\tchar f_name[ACC_FN_NAME_MAX + 1];\n#        elif (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_TOS || ACC_OS_WIN16)\n\tchar u_dta[21];\n\tunsigned char f_attr;\n\tunsigned short f_time;\n\tunsigned short f_date;\n\tunsigned short f_size_low;\n\tunsigned short f_size_high;\n\tchar f_name[ACC_FN_NAME_MAX + 1];\n\tchar u_dirp;\n#        else\n\tvoid *u_dirp;\n\tchar f_name[ACC_FN_NAME_MAX + 1];\n#        endif\n} acc_dir_t;\n#        ifndef acc_dir_p\n#            define acc_dir_p acc_dir_t *\n#        endif\nACCLIB_EXTERN(int, acc_opendir) (acc_dir_p, const char *);\nACCLIB_EXTERN(int, acc_readdir) (acc_dir_p);\nACCLIB_EXTERN(int, acc_closedir) (acc_dir_p);\n#        if (ACC_CC_GNUC) && (defined(__CYGWIN__) || defined(__MINGW32__))\n#            define acc_alloca(x)     __builtin_alloca((x))\n#        elif (ACC_CC_GNUC) && (ACC_OS_CONSOLE_PS2)\n#            define acc_alloca(x)     __builtin_alloca((x))\n#        elif (ACC_CC_BORLANDC || ACC_CC_LCC) && defined(__linux__)\n#        elif (HAVE_ALLOCA)\n#            define acc_alloca(x)     ((void *) (alloca((x))))\n#        endif\n#        if (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n#            define acc_stackavail()  stackavail()\n#        elif (ACC_ARCH_I086 && ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0410))\n#            define acc_stackavail()  stackavail()\n#        elif (ACC_ARCH_I086 && ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0400))\n#            if (ACC_OS_WIN16) && (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)\n#            else\n#                define acc_stackavail()  stackavail()\n#            endif\n#        elif ((ACC_ARCH_I086 || ACC_ARCH_I386) && (ACC_CC_DMC || ACC_CC_SYMANTECC))\n#            define acc_stackavail()  stackavail()\n#        elif ((ACC_ARCH_I086) && ACC_CC_MSC && (_MSC_VER >= 700))\n#            define acc_stackavail()  _stackavail()\n#        elif ((ACC_ARCH_I086) && ACC_CC_MSC)\n#            define acc_stackavail()  stackavail()\n#        elif ((ACC_ARCH_I086 || ACC_ARCH_I386) && ACC_CC_TURBOC && (__TURBOC__ >= 0x0450))\n#            define acc_stackavail()  stackavail()\n#        elif (ACC_ARCH_I086 && ACC_CC_TURBOC && (__TURBOC__ >= 0x0400))\nACC_EXTERN_C size_t __cdecl stackavail(void);\n#            define acc_stackavail()  stackavail()\n#        elif ((ACC_ARCH_I086 || ACC_ARCH_I386) && (ACC_CC_WATCOMC))\n#            define acc_stackavail()  stackavail()\n#        elif (ACC_ARCH_I086 && ACC_CC_ZORTECHC)\n#            define acc_stackavail()  _chkstack()\n#        endif\nACCLIB_EXTERN(acclib_handle_t, acc_get_osfhandle) (int);\nACCLIB_EXTERN(const char *, acc_getenv) (const char *);\nACCLIB_EXTERN(int, acc_isatty) (int);\nACCLIB_EXTERN(int, acc_mkdir) (const char *, unsigned);\nACCLIB_EXTERN(int, acc_rmdir) (const char *);\nACCLIB_EXTERN(int, acc_response) (int *, char ***);\nACCLIB_EXTERN(int, acc_set_binmode) (int, int);\n#        if defined(acc_int32e_t)\nACCLIB_EXTERN(acc_int32e_t, acc_muldiv32s) (acc_int32e_t, acc_int32e_t, acc_int32e_t);\nACCLIB_EXTERN(acc_uint32e_t, acc_muldiv32u) (acc_uint32e_t, acc_uint32e_t, acc_uint32e_t);\n#        endif\nACCLIB_EXTERN(void, acc_wildargv) (int *, char ***);\nACCLIB_EXTERN_NOINLINE(void, acc_debug_break) (void);\nACCLIB_EXTERN_NOINLINE(void, acc_debug_nop) (void);\nACCLIB_EXTERN_NOINLINE(int, acc_debug_align_check_query) (void);\nACCLIB_EXTERN_NOINLINE(int, acc_debug_align_check_enable) (int);\nACCLIB_EXTERN_NOINLINE(unsigned, acc_debug_running_on_qemu) (void);\nACCLIB_EXTERN_NOINLINE(unsigned, acc_debug_running_on_valgrind) (void);\n#        if !defined(acc_int64l_t) || defined(ACC_CFG_NO_DOUBLE)\n#            undef __ACCLIB_PCLOCK_USE_RDTSC\n#            undef __ACCLIB_PCLOCK_USE_PERFCTR\n#            undef __ACCLIB_UCLOCK_USE_RDTSC\n#            undef __ACCLIB_UCLOCK_USE_PERFCTR\n#        else\ntypedef struct {\n\tvoid *h;\n\tint mode;\n\tdouble tsc_to_seconds;\n\tunsigned cpu_type, cpu_features, cpu_khz, cpu_nrctrs;\n\tconst char *cpu_name;\n} acc_perfctr_handle_t;\ntypedef struct {\n\tacc_uint64l_t tsc;\n#            if (ACC_OS_POSIX_LINUX)\n\tacc_uint64l_t pmc[18];\n#            else\n\tacc_uint64l_t pmc[1];\n#            endif\n} acc_perfctr_clock_t;\n#            ifndef acc_perfctr_handle_p\n#                define acc_perfctr_handle_p acc_perfctr_handle_t *\n#            endif\n#            ifndef acc_perfctr_clock_p\n#                define acc_perfctr_clock_p acc_perfctr_clock_t *\n#            endif\nACCLIB_EXTERN(int, acc_perfctr_open) (acc_perfctr_handle_p);\nACCLIB_EXTERN(int, acc_perfctr_close) (acc_perfctr_handle_p);\nACCLIB_EXTERN(void, acc_perfctr_read) (acc_perfctr_handle_p, acc_perfctr_clock_p);\n#            if !defined(ACC_CFG_NO_DOUBLE)\nACCLIB_EXTERN(double, acc_perfctr_get_elapsed) (acc_perfctr_handle_p, const acc_perfctr_clock_p, const acc_perfctr_clock_p);\nACCLIB_EXTERN(double, acc_perfctr_get_elapsed_tsc) (acc_perfctr_handle_p, acc_uint64l_t);\n#            endif\nACCLIB_EXTERN(int, acc_perfctr_flush_cpu_cache) (acc_perfctr_handle_p, unsigned);\n#        endif\n#        if defined(acc_int32e_t)\nACCLIB_EXTERN(int, acc_tsc_read) (acc_uint32e_t *);\n#        else\n#            undef __ACCLIB_PCLOCK_USE_RDTSC\n#            undef __ACCLIB_UCLOCK_USE_RDTSC\n#        endif\nstruct acc_pclock_handle_t;\nstruct acc_pclock_t;\ntypedef struct acc_pclock_handle_t acc_pclock_handle_t;\ntypedef struct acc_pclock_t acc_pclock_t;\n#        ifndef acc_pclock_handle_p\n#            define acc_pclock_handle_p acc_pclock_handle_t *\n#        endif\n#        ifndef acc_pclock_p\n#            define acc_pclock_p acc_pclock_t *\n#        endif\n#        define ACC_PCLOCK_REALTIME             0\n#        define ACC_PCLOCK_MONOTONIC            1\n#        define ACC_PCLOCK_PROCESS_CPUTIME_ID   2\n#        define ACC_PCLOCK_THREAD_CPUTIME_ID    3\n#        define ACC_PCLOCK_REALTIME_HR          4\n#        define ACC_PCLOCK_MONOTONIC_HR         5\nstruct acc_pclock_handle_t {\n\tacclib_handle_t h;\n\tint mode;\n\tconst char *name;\n\tint (*gettime) (acc_pclock_handle_p, acc_pclock_p);\n#        if defined(acc_int64l_t)\n\tacc_uint64l_t ticks_base;\n#        endif\n#        if defined(__ACCLIB_PCLOCK_USE_PERFCTR)\n\tacc_perfctr_handle_t pch;\n#        endif\n};\nstruct acc_pclock_t {\n#        if defined(acc_int64l_t)\n\tacc_int64l_t tv_sec;\n#        else\n\tacc_int32l_t tv_sec_high;\n\tacc_uint32l_t tv_sec_low;\n#        endif\n\tacc_uint32l_t tv_nsec;\n};\nACCLIB_EXTERN(int, acc_pclock_open) (acc_pclock_handle_p, int);\nACCLIB_EXTERN(int, acc_pclock_open_default) (acc_pclock_handle_p);\nACCLIB_EXTERN(int, acc_pclock_close) (acc_pclock_handle_p);\nACCLIB_EXTERN(void, acc_pclock_read) (acc_pclock_handle_p, acc_pclock_p);\n#        if !defined(ACC_CFG_NO_DOUBLE)\nACCLIB_EXTERN(double, acc_pclock_get_elapsed) (acc_pclock_handle_p, const acc_pclock_p, const acc_pclock_p);\n#        endif\nACCLIB_EXTERN(int, acc_pclock_flush_cpu_cache) (acc_pclock_handle_p, unsigned);\n#        if !defined(acc_int64l_t) || defined(ACC_CFG_NO_DOUBLE)\n#            undef __ACCLIB_UCLOCK_USE_QPC\n#        elif (ACC_OS_CYGWIN || ACC_OS_EMX || ACC_OS_WIN32 || ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H)\n#            define __ACCLIB_UCLOCK_USE_QPC 1\n#        else\n#            undef __ACCLIB_UCLOCK_USE_QPC\n#        endif\ntypedef struct {\n\tacclib_handle_t h;\n\tint mode;\n\tconst char *name;\n#        if defined(__ACCLIB_UCLOCK_USE_PERFCTR)\n\tacc_perfctr_handle_t pch;\n#        endif\n#        if defined(__ACCLIB_UCLOCK_USE_QPC)\n\tdouble qpf;\n#        endif\n} acc_uclock_handle_t;\ntypedef struct {\n\tunion {\n\t\tacc_uint32l_t t32;\n#        if !(ACC_OS_DOS16 || ACC_OS_WIN16)\n#            if !defined(ACC_CFG_NO_DOUBLE)\n\t\tdouble td;\n#            endif\n#            if defined(acc_int64l_t)\n\t\tacc_int64l_t t64;\n#            endif\n#        endif\n\t} ticks;\n#        if defined(__ACCLIB_UCLOCK_USE_RDTSC)\n\tacc_uint64l_t tsc;\n#        endif\n#        if defined(__ACCLIB_UCLOCK_USE_PERFCTR)\n\tacc_perfctr_clock_t pcc;\n#        endif\n#        if defined(__ACCLIB_UCLOCK_USE_QPC)\n\tacc_int64l_t qpc;\n#        endif\n} acc_uclock_t;\n#        ifndef acc_uclock_handle_p\n#            define acc_uclock_handle_p acc_uclock_handle_t *\n#        endif\n#        ifndef acc_uclock_p\n#            define acc_uclock_p acc_uclock_t *\n#        endif\nACCLIB_EXTERN(int, acc_uclock_open) (acc_uclock_handle_p);\nACCLIB_EXTERN(int, acc_uclock_close) (acc_uclock_handle_p);\nACCLIB_EXTERN(void, acc_uclock_read) (acc_uclock_handle_p, acc_uclock_p);\n#        if !defined(ACC_CFG_NO_DOUBLE)\nACCLIB_EXTERN(double, acc_uclock_get_elapsed) (acc_uclock_handle_p, const acc_uclock_p, const acc_uclock_p);\n#        endif\nACCLIB_EXTERN(int, acc_uclock_flush_cpu_cache) (acc_uclock_handle_p, unsigned);\nstruct acc_getopt_t;\ntypedef struct acc_getopt_t acc_getopt_t;\n#        ifndef acc_getopt_p\n#            define acc_getopt_p acc_getopt_t *\n#        endif\nstruct acc_getopt_longopt_t;\ntypedef struct acc_getopt_longopt_t acc_getopt_longopt_t;\n#        ifndef acc_getopt_longopt_p\n#            define acc_getopt_longopt_p acc_getopt_longopt_t *\n#        endif\nstruct acc_getopt_longopt_t {\n\tconst char *name;\n\tint has_arg;\n\tint *flag;\n\tint val;\n};\nstruct acc_getopt_t {\n\tvoid *user;\n\tchar *optarg;\n\tvoid (*opterr) (acc_getopt_p, const char *, void *);\n\tint optind;\n\tint optopt;\n\tint errcount;\n\tconst char *progname;\n\tint argc;\n\tchar **argv;\n\tint eof;\n\tint shortpos;\n\tint pending_rotate_first, pending_rotate_middle;\n};\nenum { ACC_GETOPT_NO_ARG, ACC_GETOPT_REQUIRED_ARG, ACC_GETOPT_OPTIONAL_ARG, ACC_GETOPT_EXACT_ARG = 0x10 };\nenum { ACC_GETOPT_PERMUTE, ACC_GETOPT_RETURN_IN_ORDER, ACC_GETOPT_REQUIRE_ORDER };\nACCLIB_EXTERN(void, acc_getopt_init) (acc_getopt_p g, int start_argc, int argc, char **argv);\nACCLIB_EXTERN(int, acc_getopt) (acc_getopt_p g, const char *shortopts, const acc_getopt_longopt_p longopts, int *longind);\ntypedef struct {\n\tacc_uint32l_t seed;\n} acc_rand31_t;\n#        ifndef acc_rand31_p\n#            define acc_rand31_p acc_rand31_t *\n#        endif\nACCLIB_EXTERN(void, acc_srand31) (acc_rand31_p, acc_uint32l_t);\nACCLIB_EXTERN(acc_uint32l_t, acc_rand31) (acc_rand31_p);\n#        if defined(acc_int64l_t)\ntypedef struct {\n\tacc_uint64l_t seed;\n} acc_rand48_t;\n#            ifndef acc_rand48_p\n#                define acc_rand48_p acc_rand48_t *\n#            endif\nACCLIB_EXTERN(void, acc_srand48) (acc_rand48_p, acc_uint32l_t);\nACCLIB_EXTERN(acc_uint32l_t, acc_rand48) (acc_rand48_p);\nACCLIB_EXTERN(acc_uint32l_t, acc_rand48_r32) (acc_rand48_p);\n#        endif\n#        if defined(acc_int64l_t)\ntypedef struct {\n\tacc_uint64l_t seed;\n} acc_rand64_t;\n#            ifndef acc_rand64_p\n#                define acc_rand64_p acc_rand64_t *\n#            endif\nACCLIB_EXTERN(void, acc_srand64) (acc_rand64_p, acc_uint64l_t);\nACCLIB_EXTERN(acc_uint32l_t, acc_rand64) (acc_rand64_p);\nACCLIB_EXTERN(acc_uint32l_t, acc_rand64_r32) (acc_rand64_p);\n#        endif\ntypedef struct {\n\tunsigned n;\n\tacc_uint32l_t s[624];\n} acc_randmt_t;\n#        ifndef acc_randmt_p\n#            define acc_randmt_p acc_randmt_t *\n#        endif\nACCLIB_EXTERN(void, acc_srandmt) (acc_randmt_p, acc_uint32l_t);\nACCLIB_EXTERN(acc_uint32l_t, acc_randmt) (acc_randmt_p);\nACCLIB_EXTERN(acc_uint32l_t, acc_randmt_r32) (acc_randmt_p);\n#        if defined(acc_int64l_t)\ntypedef struct {\n\tunsigned n;\n\tacc_uint64l_t s[312];\n} acc_randmt64_t;\n#            ifndef acc_randmt64_p\n#                define acc_randmt64_p acc_randmt64_t *\n#            endif\nACCLIB_EXTERN(void, acc_srandmt64) (acc_randmt64_p, acc_uint64l_t);\nACCLIB_EXTERN(acc_uint64l_t, acc_randmt64_r64) (acc_randmt64_p);\n#        endif\n#        define ACC_SPAWN_P_WAIT    0\n#        define ACC_SPAWN_P_NOWAIT  1\nACCLIB_EXTERN(int, acc_spawnv) (int mode, const char *fn, const char *const *argv);\nACCLIB_EXTERN(int, acc_spawnvp) (int mode, const char *fn, const char *const *argv);\nACCLIB_EXTERN(int, acc_spawnve) (int mode, const char *fn, const char *const *argv, const char *const envp);\n#    endif\n#endif\n#if defined(ACC_WANT_ACC_CXX_H)\n#    undef ACC_WANT_ACC_CXX_H\n#    ifndef __ACC_CXX_H_INCLUDED\n#        define __ACC_CXX_H_INCLUDED 1\n#        if defined(__cplusplus)\n#            if defined(ACC_CXX_NOTHROW)\n#            elif (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020800ul))\n#            elif (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0450))\n#            elif (ACC_CC_HIGHC)\n#            elif (ACC_CC_MSC && (_MSC_VER < 1100))\n#            elif (ACC_CC_NDPC)\n#            elif (ACC_CC_TURBOC)\n#            elif (ACC_CC_WATCOMC && !defined(_CPPUNWIND))\n#            elif (ACC_CC_ZORTECHC)\n#            else\n#                define ACC_CXX_NOTHROW   throw()\n#            endif\n#            if !defined(ACC_CXX_NOTHROW)\n#                define ACC_CXX_NOTHROW\n#            endif\n#            if defined(__ACC_CXX_DO_NEW)\n#            elif (ACC_CC_NDPC || ACC_CC_PGI)\n#                define __ACC_CXX_DO_NEW          { return 0; }\n#            elif ((ACC_CC_BORLANDC || ACC_CC_TURBOC) && ACC_ARCH_I086)\n#                define __ACC_CXX_DO_NEW          { return 0; }\n#            else\n#                define __ACC_CXX_DO_NEW          ;\n#            endif\n#            if defined(__ACC_CXX_DO_DELETE)\n#            elif (ACC_CC_BORLANDC || ACC_CC_TURBOC)\n#                define __ACC_CXX_DO_DELETE       { }\n#            else\n#                define __ACC_CXX_DO_DELETE       ACC_CXX_NOTHROW { }\n#            endif\n#            if (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0450))\n#            elif (ACC_CC_MSC && ACC_MM_HUGE)\n#                define ACC_CXX_DISABLE_NEW_DELETE private:\n#            elif (ACC_CC_MSC && (_MSC_VER < 1100))\n#            elif (ACC_CC_NDPC)\n#            elif (ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)\n#            elif (ACC_CC_TURBOC)\n#            elif (ACC_CC_WATCOMC && (__WATCOMC__ < 1100))\n#            else\n#                define __ACC_CXX_HAVE_ARRAY_NEW 1\n#            endif\n#            if (__ACC_CXX_HAVE_ARRAY_NEW)\n#                define __ACC_CXX_HAVE_PLACEMENT_NEW 1\n#            endif\n#            if (__ACC_CXX_HAVE_PLACEMENT_NEW)\n#                if (ACC_CC_GNUC >= 0x030000ul)\n#                    define __ACC_CXX_HAVE_PLACEMENT_DELETE 1\n#                elif (ACC_CC_INTELC)\n#                    define __ACC_CXX_HAVE_PLACEMENT_DELETE 1\n#                elif (ACC_CC_MSC && (_MSC_VER >= 1200))\n#                    define __ACC_CXX_HAVE_PLACEMENT_DELETE 1\n#                elif (ACC_CC_LLVM || ACC_CC_PATHSCALE)\n#                    define __ACC_CXX_HAVE_PLACEMENT_DELETE 1\n#                elif (ACC_CC_PGI)\n#                    define __ACC_CXX_HAVE_PLACEMENT_DELETE 1\n#                endif\n#            endif\n#            if defined(ACC_CXX_DISABLE_NEW_DELETE)\n#            elif defined(new) || defined(delete)\n#                define ACC_CXX_DISABLE_NEW_DELETE private:\n#            elif (ACC_CC_GNUC && (ACC_CC_GNUC < 0x025b00ul))\n#                define ACC_CXX_DISABLE_NEW_DELETE private:\n#            elif  (ACC_CC_HIGHC)\n#                define ACC_CXX_DISABLE_NEW_DELETE private:\n#            elif !defined(__ACC_CXX_HAVE_ARRAY_NEW)\n#                define ACC_CXX_DISABLE_NEW_DELETE \\\n        protected: static void operator delete(void*) __ACC_CXX_DO_DELETE \\\n        protected: static void* operator new(size_t) __ACC_CXX_DO_NEW \\\n        private:\n#            else\n#                define ACC_CXX_DISABLE_NEW_DELETE \\\n        protected: static void operator delete(void*) __ACC_CXX_DO_DELETE \\\n                   static void operator delete[](void*) __ACC_CXX_DO_DELETE \\\n        private:   static void* operator new(size_t)  __ACC_CXX_DO_NEW \\\n                   static void* operator new[](size_t) __ACC_CXX_DO_NEW\n#            endif\n#            if defined(ACC_CXX_TRIGGER_FUNCTION)\n#            else\n#                define ACC_CXX_TRIGGER_FUNCTION \\\n        protected: virtual const void* acc_cxx_trigger_function() const; \\\n        private:\n#            endif\n#            if defined(ACC_CXX_TRIGGER_FUNCTION_IMPL)\n#            else\n#                define ACC_CXX_TRIGGER_FUNCTION_IMPL(klass) \\\n        const void* klass::acc_cxx_trigger_function() const { return 0; }\n#            endif\n#        endif\n#    endif\n#endif\n#if defined(ACC_WANT_ACC_CHK_CH)\n#    undef ACC_WANT_ACC_CHK_CH\n#    if !defined(ACCCHK_ASSERT)\n#        define ACCCHK_ASSERT(expr)   ACC_COMPILE_TIME_ASSERT_HEADER(expr)\n#    endif\n#    if !defined(ACCCHK_ASSERT_SIGN_T)\n#        define ACCCHK_ASSERT_SIGN_T(type,relop) \\\n        ACCCHK_ASSERT( (type) (-1)       relop  (type) 0 ) \\\n        ACCCHK_ASSERT( (type) (~(type)0) relop  (type) 0 ) \\\n        ACCCHK_ASSERT( (type) (~(type)0) ==     (type) (-1) )\n#    endif\n#    if !defined(ACCCHK_ASSERT_IS_SIGNED_T)\n#        define ACCCHK_ASSERT_IS_SIGNED_T(type)       ACCCHK_ASSERT_SIGN_T(type,<)\n#    endif\n#    if !defined(ACCCHK_ASSERT_IS_UNSIGNED_T)\n#        if (ACC_BROKEN_INTEGRAL_PROMOTION)\n#            define ACCCHK_ASSERT_IS_UNSIGNED_T(type) \\\n        ACCCHK_ASSERT( (type) (-1) > (type) 0 )\n#        else\n#            define ACCCHK_ASSERT_IS_UNSIGNED_T(type)   ACCCHK_ASSERT_SIGN_T(type,>)\n#        endif\n#    endif\n#    if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0550) && (__BORLANDC__ < 0x0560))\n#        pragma option push -w-8055\n#    elif (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0530) && (__BORLANDC__ < 0x0550))\n#        pragma option push -w-osh\n#    endif\n#    if (ACC_0xffffffffL - ACC_UINT32_C(4294967294) != 1)\n#        error \"preprocessor error 1\"\n#    endif\n#    if (ACC_0xffffffffL - ACC_UINT32_C(0xfffffffd) != 2)\n#        error \"preprocessor error 2\"\n#    endif\n#    define ACCCHK_VAL  1\n#    define ACCCHK_TMP1 ACCCHK_VAL\n#    undef ACCCHK_VAL\n#    define ACCCHK_VAL  2\n#    define ACCCHK_TMP2 ACCCHK_VAL\n#    if (ACCCHK_TMP1 != 2)\n#        error \"preprocessor error 3a\"\n#    endif\n#    if (ACCCHK_TMP2 != 2)\n#        error \"preprocessor error 3b\"\n#    endif\n#    undef ACCCHK_VAL\n#    if (ACCCHK_TMP2)\n#        error \"preprocessor error 3c\"\n#    endif\n#    if (ACCCHK_TMP2 + 0 != 0)\n#        error \"preprocessor error 3d\"\n#    endif\n#    undef ACCCHK_TMP1\n#    undef ACCCHK_TMP2\n#    if 0 || defined(ACCCHK_CFG_PEDANTIC)\n#        if (ACC_ARCH_MIPS) && defined(_MIPS_SZINT)\nACCCHK_ASSERT((_MIPS_SZINT) == 8 * sizeof(int))\n#        endif\n#        if (ACC_ARCH_MIPS) && defined(_MIPS_SZLONG)\n\tACCCHK_ASSERT((_MIPS_SZLONG) == 8 * sizeof(long))\n#        endif\n#        if (ACC_ARCH_MIPS) && defined(_MIPS_SZPTR)\n\tACCCHK_ASSERT((_MIPS_SZPTR) == 8 * sizeof(void *))\n#        endif\n#    endif\n\tACCCHK_ASSERT(1 == 1)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1u, 2) == 3)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1u, 8) == 255)\n#    if (SIZEOF_INT >= 2)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1, 15) == 32767)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1u, 16) == 0xffffU)\n#    else\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1ul, 16) == 0xffffUL)\n#    endif\n#    if (SIZEOF_INT >= 4)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1, 31) == 2147483647)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1u, 32) == 0xffffffffU)\n#    endif\n#    if (SIZEOF_LONG >= 4)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1ul, 32) == 0xffffffffUL)\n#    endif\n#    if (SIZEOF_LONG >= 8)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1ul, 64) == 0xffffffffffffffffUL)\n#    endif\n#    if !defined(ACC_BROKEN_INTEGRAL_PROMOTION)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1u, SIZEOF_INT * 8) == ~0u)\n\tACCCHK_ASSERT(__ACC_MASK_GEN(1ul, SIZEOF_LONG * 8) == ~0ul)\n#    endif\n#    if !defined(ACC_BROKEN_SIGNED_RIGHT_SHIFT)\n\tACCCHK_ASSERT(((-1) >> 7) == -1)\n#    endif\n\tACCCHK_ASSERT(((1) >> 7) == 0)\n\tACCCHK_ASSERT((~0l & ~0) == ~0l)\n\tACCCHK_ASSERT((~0l & ~0u) == ~0u)\n\tACCCHK_ASSERT((~0ul & ~0) == ~0ul)\n\tACCCHK_ASSERT((~0ul & ~0u) == ~0u)\n#    if defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0150)\n#    elif (SIZEOF_INT == 2)\n\tACCCHK_ASSERT((~0l & ~0u) == 0xffffU)\n\tACCCHK_ASSERT((~0ul & ~0u) == 0xffffU)\n#    elif (SIZEOF_INT == 4)\n\tACCCHK_ASSERT((~0l & ~0u) == 0xffffffffU)\n\tACCCHK_ASSERT((~0ul & ~0u) == 0xffffffffU)\n#    endif\nACCCHK_ASSERT_IS_SIGNED_T(signed char) ACCCHK_ASSERT_IS_UNSIGNED_T(unsigned char) ACCCHK_ASSERT(sizeof(signed char) == sizeof(char))\n\tACCCHK_ASSERT(sizeof(unsigned char) == sizeof(char))\n\tACCCHK_ASSERT(sizeof(char) == 1)\n#    if (ACC_CC_CILLY) && (!defined(__CILLY__) || (__CILLY__ < 0x010302L))\n#    else\n\tACCCHK_ASSERT(sizeof(char) == sizeof((char) 0))\n#    endif\n#    if defined(__cplusplus)\n\tACCCHK_ASSERT(sizeof('\\0') == sizeof(char))\n#    else\n#        if (ACC_CC_DMC)\n#        else\n\tACCCHK_ASSERT(sizeof('\\0') == sizeof(int))\n#        endif\n#    endif\n#    if defined(__acc_alignof)\n\tACCCHK_ASSERT(__acc_alignof(char) == 1)\n\tACCCHK_ASSERT(__acc_alignof(signed char) == 1)\n\tACCCHK_ASSERT(__acc_alignof(unsigned char) == 1)\n#        if defined(acc_int16e_t)\n\tACCCHK_ASSERT(__acc_alignof(acc_int16e_t) >= 1)\n\tACCCHK_ASSERT(__acc_alignof(acc_int16e_t) <= 2)\n#        endif\n#        if defined(acc_int32e_t)\n\tACCCHK_ASSERT(__acc_alignof(acc_int32e_t) >= 1)\n\tACCCHK_ASSERT(__acc_alignof(acc_int32e_t) <= 4)\n#        endif\n#    endif\nACCCHK_ASSERT_IS_SIGNED_T(short) ACCCHK_ASSERT_IS_UNSIGNED_T(unsigned short) ACCCHK_ASSERT(sizeof(short) == sizeof(unsigned short))\n#    if !defined(ACC_ABI_I8LP16)\n\tACCCHK_ASSERT(sizeof(short) >= 2)\n#    endif\n\tACCCHK_ASSERT(sizeof(short) >= sizeof(char))\n#    if (ACC_CC_CILLY) && (!defined(__CILLY__) || (__CILLY__ < 0x010302L))\n#    else\n\tACCCHK_ASSERT(sizeof(short) == sizeof((short) 0))\n#    endif\n#    if (SIZEOF_SHORT > 0)\n\tACCCHK_ASSERT(sizeof(short) == SIZEOF_SHORT)\n#    endif\nACCCHK_ASSERT_IS_SIGNED_T(int) ACCCHK_ASSERT_IS_UNSIGNED_T(unsigned int) ACCCHK_ASSERT(sizeof(int) == sizeof(unsigned int))\n#    if !defined(ACC_ABI_I8LP16)\n\tACCCHK_ASSERT(sizeof(int) >= 2)\n#    endif\n\tACCCHK_ASSERT(sizeof(int) >= sizeof(short))\n\tACCCHK_ASSERT(sizeof(int) == sizeof(0))\n\tACCCHK_ASSERT(sizeof(int) == sizeof((int) 0))\n#    if (SIZEOF_INT > 0)\n\tACCCHK_ASSERT(sizeof(int) == SIZEOF_INT)\n#    endif\n\tACCCHK_ASSERT(sizeof(0) == sizeof(int))\nACCCHK_ASSERT_IS_SIGNED_T(long) ACCCHK_ASSERT_IS_UNSIGNED_T(unsigned long) ACCCHK_ASSERT(sizeof(long) == sizeof(unsigned long))\n#    if !defined(ACC_ABI_I8LP16)\n\tACCCHK_ASSERT(sizeof(long) >= 4)\n#    endif\n\tACCCHK_ASSERT(sizeof(long) >= sizeof(int))\n\tACCCHK_ASSERT(sizeof(long) == sizeof(0L))\n\tACCCHK_ASSERT(sizeof(long) == sizeof((long) 0))\n#    if (SIZEOF_LONG > 0)\n\tACCCHK_ASSERT(sizeof(long) == SIZEOF_LONG)\n#    endif\n\tACCCHK_ASSERT(sizeof(0L) == sizeof(long))\n\tACCCHK_ASSERT_IS_UNSIGNED_T(size_t)\n\tACCCHK_ASSERT(sizeof(size_t) >= sizeof(int))\n\tACCCHK_ASSERT(sizeof(size_t) == sizeof(sizeof(0)))\n#    if (SIZEOF_SIZE_T > 0)\n\tACCCHK_ASSERT(sizeof(size_t) == SIZEOF_SIZE_T)\n#    endif\n\tACCCHK_ASSERT_IS_SIGNED_T(ptrdiff_t)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) >= sizeof(int))\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t))\n#    if !defined(ACC_BROKEN_SIZEOF)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof((char *)0 - (char *)0))\n#        if (ACC_HAVE_MM_HUGE_PTR)\n\tACCCHK_ASSERT(4 == sizeof((char __huge *) 0 - (char __huge *)0))\n#        endif\n#    endif\n#    if (SIZEOF_PTRDIFF_T > 0)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == SIZEOF_PTRDIFF_T)\n#    endif\n\tACCCHK_ASSERT(sizeof(void *) >= sizeof(char *))\n#    if (SIZEOF_VOID_P > 0)\n\tACCCHK_ASSERT(sizeof(void *) == SIZEOF_VOID_P)\n\tACCCHK_ASSERT(sizeof(char *) == SIZEOF_VOID_P)\n#    endif\n#    if (ACC_HAVE_MM_HUGE_PTR)\n\tACCCHK_ASSERT(4 == sizeof(void __huge *))\n\tACCCHK_ASSERT(4 == sizeof(char __huge *))\n#    endif\n#    if defined(ACC_ABI_I8LP16)\n\tACCCHK_ASSERT((((1u << 7) + 1) >> 7) == 1)\n\tACCCHK_ASSERT((((1ul << 15) + 1) >> 15) == 1)\n#    else\n\tACCCHK_ASSERT((((1u << 15) + 1) >> 15) == 1)\n\tACCCHK_ASSERT((((1ul << 31) + 1) >> 31) == 1)\n#    endif\n#    if defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0150)\n#    elif 1 && (ACC_CC_SUNPROC) && !defined(ACCCHK_CFG_PEDANTIC)\n#    else\n\tACCCHK_ASSERT((1 << (8 * SIZEOF_INT - 1)) < 0)\n#    endif\n\tACCCHK_ASSERT((1u << (8 * SIZEOF_INT - 1)) > 0)\n#    if 1 && (ACC_CC_SUNPROC) && !defined(ACCCHK_CFG_PEDANTIC)\n#    else\n\tACCCHK_ASSERT((1l << (8 * SIZEOF_LONG - 1)) < 0)\n#    endif\n\tACCCHK_ASSERT((1ul << (8 * SIZEOF_LONG - 1)) > 0)\n#    if defined(acc_int16e_t)\n\tACCCHK_ASSERT(sizeof(acc_int16e_t) == 2)\n\tACCCHK_ASSERT(sizeof(acc_int16e_t) == SIZEOF_ACC_INT16E_T)\n\tACCCHK_ASSERT(sizeof(acc_uint16e_t) == 2)\n\tACCCHK_ASSERT(sizeof(acc_int16e_t) == sizeof(acc_uint16e_t))\n\tACCCHK_ASSERT_IS_SIGNED_T(acc_int16e_t)\n\tACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint16e_t)\n#        if defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0150)\n#        else\n\tACCCHK_ASSERT(((acc_uint16e_t) (~(acc_uint16e_t) 0ul) >> 15) == 1)\n#        endif\n\tACCCHK_ASSERT((acc_int16e_t) (1 + ~(acc_int16e_t) 0) == 0)\n#        if defined(ACCCHK_CFG_PEDANTIC)\n\tACCCHK_ASSERT((acc_uint16e_t) (1 + ~(acc_uint16e_t) 0) == 0)\n#        endif\n#    endif\n#    if defined(acc_int32e_t)\n\tACCCHK_ASSERT(sizeof(acc_int32e_t) == 4)\n\tACCCHK_ASSERT(sizeof(acc_int32e_t) == SIZEOF_ACC_INT32E_T)\n\tACCCHK_ASSERT(sizeof(acc_uint32e_t) == 4)\n\tACCCHK_ASSERT(sizeof(acc_int32e_t) == sizeof(acc_uint32e_t))\n\tACCCHK_ASSERT_IS_SIGNED_T(acc_int32e_t)\n\tACCCHK_ASSERT(((((acc_int32e_t) 1 << 30) + 1) >> 30) == 1)\n\tACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint32e_t)\n\tACCCHK_ASSERT(((((acc_uint32e_t) 1 << 31) + 1) >> 31) == 1)\n\tACCCHK_ASSERT(((acc_uint32e_t) (~(acc_uint32e_t) 0ul) >> 31) == 1)\n\tACCCHK_ASSERT((acc_int32e_t) (1 + ~(acc_int32e_t) 0) == 0)\n#        if defined(ACCCHK_CFG_PEDANTIC)\n\tACCCHK_ASSERT((acc_uint32e_t) (1 + ~(acc_uint32e_t) 0) == 0)\n#        endif\n#    endif\n#    if defined(acc_int32e_t)\n\tACCCHK_ASSERT(sizeof(acc_int32l_t) >= sizeof(acc_int32e_t))\n#    endif\n\tACCCHK_ASSERT(sizeof(acc_int32l_t) >= 4)\n\tACCCHK_ASSERT(sizeof(acc_int32l_t) == SIZEOF_ACC_INT32L_T)\n\tACCCHK_ASSERT(sizeof(acc_uint32l_t) >= 4)\n\tACCCHK_ASSERT(sizeof(acc_int32l_t) == sizeof(acc_uint32l_t))\n\tACCCHK_ASSERT_IS_SIGNED_T(acc_int32l_t)\n\tACCCHK_ASSERT(((((acc_int32l_t) 1 << 30) + 1) >> 30) == 1)\n\tACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint32l_t)\n\tACCCHK_ASSERT(((((acc_uint32l_t) 1 << 31) + 1) >> 31) == 1)\n\tACCCHK_ASSERT(sizeof(acc_int32f_t) >= sizeof(int))\n#    if defined(acc_int32e_t)\n\tACCCHK_ASSERT(sizeof(acc_int32f_t) >= sizeof(acc_int32e_t))\n#    endif\n\tACCCHK_ASSERT(sizeof(acc_int32f_t) >= sizeof(acc_int32l_t))\n\tACCCHK_ASSERT(sizeof(acc_int32f_t) >= 4)\n\tACCCHK_ASSERT(sizeof(acc_int32f_t) >= sizeof(acc_int32l_t))\n\tACCCHK_ASSERT(sizeof(acc_int32f_t) == SIZEOF_ACC_INT32F_T)\n\tACCCHK_ASSERT(sizeof(acc_uint32f_t) >= 4)\n\tACCCHK_ASSERT(sizeof(acc_uint32f_t) >= sizeof(acc_uint32l_t))\n\tACCCHK_ASSERT(sizeof(acc_int32f_t) == sizeof(acc_uint32f_t))\n\tACCCHK_ASSERT_IS_SIGNED_T(acc_int32f_t)\n\tACCCHK_ASSERT(((((acc_int32f_t) 1 << 30) + 1) >> 30) == 1)\n\tACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint32f_t)\n\tACCCHK_ASSERT(((((acc_uint32f_t) 1 << 31) + 1) >> 31) == 1)\n#    if defined(acc_int64e_t)\n\tACCCHK_ASSERT(sizeof(acc_int64e_t) == 8)\n\tACCCHK_ASSERT(sizeof(acc_int64e_t) == SIZEOF_ACC_INT64E_T)\n\tACCCHK_ASSERT(sizeof(acc_uint64e_t) == 8)\n\tACCCHK_ASSERT(sizeof(acc_int64e_t) == sizeof(acc_uint64e_t))\n\tACCCHK_ASSERT_IS_SIGNED_T(acc_int64e_t)\n#        if (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0530))\n#        else\n\tACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint64e_t)\n#        endif\n#    endif\n#    if defined(acc_int64l_t)\n#        if defined(acc_int64e_t)\n\tACCCHK_ASSERT(sizeof(acc_int64l_t) >= sizeof(acc_int64e_t))\n#        endif\n\tACCCHK_ASSERT(sizeof(acc_int64l_t) >= 8)\n\tACCCHK_ASSERT(sizeof(acc_int64l_t) == SIZEOF_ACC_INT64L_T)\n\tACCCHK_ASSERT(sizeof(acc_uint64l_t) >= 8)\n\tACCCHK_ASSERT(sizeof(acc_int64l_t) == sizeof(acc_uint64l_t))\n\tACCCHK_ASSERT_IS_SIGNED_T(acc_int64l_t)\n\tACCCHK_ASSERT(((((acc_int64l_t) 1 << 62) + 1) >> 62) == 1)\n\tACCCHK_ASSERT((((ACC_INT64_C(1) << 62) + 1) >> 62) == 1)\n#        if (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0530))\n#        else\n\tACCCHK_ASSERT_IS_UNSIGNED_T(acc_uint64l_t)\n\tACCCHK_ASSERT(ACC_UINT64_C(18446744073709551615) > 0)\n#        endif\n\tACCCHK_ASSERT(((((acc_uint64l_t) 1 << 63) + 1) >> 63) == 1)\n\tACCCHK_ASSERT((((ACC_UINT64_C(1) << 63) + 1) >> 63) == 1)\n#        if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020600ul))\n\tACCCHK_ASSERT(ACC_INT64_C(9223372036854775807) > ACC_INT64_C(0))\n#        else\n\tACCCHK_ASSERT(ACC_INT64_C(9223372036854775807) > 0)\n#        endif\n\tACCCHK_ASSERT(ACC_INT64_C(-9223372036854775807) - 1 < 0)\n\tACCCHK_ASSERT(ACC_INT64_C(9223372036854775807) % ACC_INT32_C(2147483629) == 721)\n\tACCCHK_ASSERT(ACC_INT64_C(9223372036854775807) % ACC_INT32_C(2147483647) == 1)\n\tACCCHK_ASSERT(ACC_UINT64_C(9223372036854775807) % ACC_UINT32_C(2147483629) == 721)\n\tACCCHK_ASSERT(ACC_UINT64_C(9223372036854775807) % ACC_UINT32_C(2147483647) == 1)\n#    endif\n#    if !defined(__ACC_INTPTR_T_IS_POINTER)\n\tACCCHK_ASSERT_IS_SIGNED_T(acc_intptr_t)\n\tACCCHK_ASSERT_IS_UNSIGNED_T(acc_uintptr_t)\n#    endif\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) >= sizeof(void *))\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == SIZEOF_ACC_INTPTR_T)\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(acc_uintptr_t))\n#    if defined(acc_word_t)\n\tACCCHK_ASSERT(ACC_WORDSIZE == SIZEOF_ACC_WORD_T)\n\tACCCHK_ASSERT_IS_UNSIGNED_T(acc_word_t)\n\tACCCHK_ASSERT_IS_SIGNED_T(acc_sword_t)\n\tACCCHK_ASSERT(sizeof(acc_word_t) == SIZEOF_ACC_WORD_T)\n\tACCCHK_ASSERT(sizeof(acc_word_t) == sizeof(acc_sword_t))\n#    endif\n#    if defined(ACC_INT16_C)\n\tACCCHK_ASSERT(sizeof(ACC_INT16_C(0)) >= 2)\n\tACCCHK_ASSERT(sizeof(ACC_UINT16_C(0)) >= 2)\n\tACCCHK_ASSERT((ACC_UINT16_C(0xffff) >> 15) == 1)\n#    endif\n#    if defined(ACC_INT32_C)\n\tACCCHK_ASSERT(sizeof(ACC_INT32_C(0)) >= 4)\n\tACCCHK_ASSERT(sizeof(ACC_UINT32_C(0)) >= 4)\n\tACCCHK_ASSERT((ACC_UINT32_C(0xffffffff) >> 31) == 1)\n#    endif\n#    if defined(ACC_INT64_C)\n#        if (ACC_CC_BORLANDC && (__BORLANDC__ < 0x0560))\n#        else\n\tACCCHK_ASSERT(sizeof(ACC_INT64_C(0)) >= 8)\n\tACCCHK_ASSERT(sizeof(ACC_UINT64_C(0)) >= 8)\n#        endif\n\tACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) >> 63) == 1)\n\tACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) & ~0) == ACC_UINT64_C(0xffffffffffffffff))\n\tACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) & ~0l) == ACC_UINT64_C(0xffffffffffffffff))\n#        if (SIZEOF_INT == 4)\n#            if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020000ul))\n#            else\n\tACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) & ~0u) == 0xffffffffu)\n#            endif\n#        endif\n#        if (SIZEOF_LONG == 4)\n#            if (ACC_CC_GNUC && (ACC_CC_GNUC < 0x020000ul))\n#            else\n\tACCCHK_ASSERT((ACC_UINT64_C(0xffffffffffffffff) & ~0ul) == 0xfffffffful)\n#            endif\n#        endif\n#    endif\n#    if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)\n\tACCCHK_ASSERT(sizeof(void *) == 2)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == 2)\n#    elif (ACC_MM_COMPACT || ACC_MM_LARGE || ACC_MM_HUGE)\n\tACCCHK_ASSERT(sizeof(void *) == 4)\n#    endif\n#    if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_COMPACT)\n\tACCCHK_ASSERT(sizeof(void (*)(void)) == 2)\n#    elif (ACC_MM_MEDIUM || ACC_MM_LARGE || ACC_MM_HUGE)\n\tACCCHK_ASSERT(sizeof(void (*)(void)) == 4)\n#    endif\n#    if (ACC_ABI_ILP32)\n\tACCCHK_ASSERT(sizeof(int) == 4)\n\tACCCHK_ASSERT(sizeof(long) == 4)\n\tACCCHK_ASSERT(sizeof(void *) == 4)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(size_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))\n#    endif\n#    if (ACC_ABI_ILP64)\n\tACCCHK_ASSERT(sizeof(int) == 8)\n\tACCCHK_ASSERT(sizeof(long) == 8)\n\tACCCHK_ASSERT(sizeof(void *) == 8)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(size_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))\n#    endif\n#    if (ACC_ABI_IP32L64)\n\tACCCHK_ASSERT(sizeof(int) == 4)\n\tACCCHK_ASSERT(sizeof(long) == 8)\n\tACCCHK_ASSERT(sizeof(void *) == 4)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(size_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))\n#    endif\n#    if (ACC_ABI_LLP64)\n\tACCCHK_ASSERT(sizeof(int) == 4)\n\tACCCHK_ASSERT(sizeof(long) == 4)\n\tACCCHK_ASSERT(sizeof(void *) == 8)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(size_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))\n#    endif\n#    if (ACC_ABI_LP32)\n\tACCCHK_ASSERT(sizeof(int) == 2)\n\tACCCHK_ASSERT(sizeof(long) == 4)\n\tACCCHK_ASSERT(sizeof(void *) == 4)\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))\n#    endif\n#    if (ACC_ABI_LP64)\n\tACCCHK_ASSERT(sizeof(int) == 4)\n\tACCCHK_ASSERT(sizeof(long) == 8)\n\tACCCHK_ASSERT(sizeof(void *) == 8)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(size_t) == sizeof(void *))\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))\n#    endif\n#    if (ACC_ARCH_I086)\n\tACCCHK_ASSERT(sizeof(size_t) == 2)\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))\n#    elif (ACC_ARCH_I386 || ACC_ARCH_M68K)\n\tACCCHK_ASSERT(sizeof(size_t) == 4)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == 4)\n\tACCCHK_ASSERT(sizeof(acc_intptr_t) == sizeof(void *))\n#    endif\n#    if (ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_WIN32)\n\tACCCHK_ASSERT(sizeof(size_t) == 4)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == 4)\n\tACCCHK_ASSERT(sizeof(void (*)(void)) == 4)\n#    elif (ACC_OS_WIN64)\n\tACCCHK_ASSERT(sizeof(size_t) == 8)\n\tACCCHK_ASSERT(sizeof(ptrdiff_t) == 8)\n\tACCCHK_ASSERT(sizeof(void (*)(void)) == 8)\n#    endif\n#    if (ACC_CC_NDPC)\n#    elif (SIZEOF_INT > 1)\n\tACCCHK_ASSERT((int)((unsigned char)((signed char)-1)) == 255)\n#    endif\n#    if (ACC_CC_KEILC)\n#    elif (ACC_CC_NDPC)\n#    elif 1 && (ACC_CC_LCC || ACC_CC_LCCWIN32) && !defined(ACCCHK_CFG_PEDANTIC)\n#    elif 1 && (ACC_CC_SUNPROC) && !defined(ACCCHK_CFG_PEDANTIC)\n#    elif !defined(ACC_BROKEN_INTEGRAL_PROMOTION) && (SIZEOF_INT > 1)\n\tACCCHK_ASSERT((((unsigned char)128) << (int)(8 * sizeof(int) - 8)) < 0)\n#    endif\n#    if (ACC_CC_BORLANDC && (__BORLANDC__ >= 0x0530) && (__BORLANDC__ < 0x0560))\n#        pragma option pop\n#    endif\n#endif\n#if defined(ACC_WANT_ACCLIB_UA)\n#    undef ACC_WANT_ACCLIB_UA\n#    define __ACCLIB_UA_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\nACCLIB_PUBLIC(unsigned, acc_ua_get_be16) (const acc_hvoid_p p) {\n#    if defined(ACC_UA_GET_BE16)\n\treturn ACC_UA_GET_BE16(p);\n#    else\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\treturn ((unsigned)b[1]) | ((unsigned)b[0] << 8);\n#    endif\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_ua_get_be24) (const acc_hvoid_p p) {\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\treturn ((acc_uint32l_t) b[2]) | ((acc_uint32l_t) b[1] << 8) | ((acc_uint32l_t) b[0] << 16);\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_ua_get_be32) (const acc_hvoid_p p) {\n#    if defined(ACC_UA_GET_BE32)\n\treturn ACC_UA_GET_BE32(p);\n#    else\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\treturn ((acc_uint32l_t) b[3]) | ((acc_uint32l_t) b[2] << 8) | ((acc_uint32l_t) b[1] << 16) | ((acc_uint32l_t) b[0] << 24);\n#    endif\n}\n\nACCLIB_PUBLIC(void, acc_ua_set_be16)(acc_hvoid_p p, unsigned v) {\n#    if defined(ACC_UA_SET_BE16)\n\tACC_UA_SET_BE16(p, v);\n#    else\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tb[1] = (unsigned char)((v >> 0) & 0xff);\n\tb[0] = (unsigned char)((v >> 8) & 0xff);\n#    endif\n}\n\nACCLIB_PUBLIC(void, acc_ua_set_be24) (acc_hvoid_p p, acc_uint32l_t v) {\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tb[2] = (unsigned char)((v >> 0) & 0xff);\n\tb[1] = (unsigned char)((v >> 8) & 0xff);\n\tb[0] = (unsigned char)((v >> 16) & 0xff);\n}\n\nACCLIB_PUBLIC(void, acc_ua_set_be32) (acc_hvoid_p p, acc_uint32l_t v) {\n#    if defined(ACC_UA_SET_BE32)\n\tACC_UA_SET_BE32(p, v);\n#    else\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tb[3] = (unsigned char)((v >> 0) & 0xff);\n\tb[2] = (unsigned char)((v >> 8) & 0xff);\n\tb[1] = (unsigned char)((v >> 16) & 0xff);\n\tb[0] = (unsigned char)((v >> 24) & 0xff);\n#    endif\n}\n\nACCLIB_PUBLIC(unsigned, acc_ua_get_le16) (const acc_hvoid_p p) {\n#    if defined(ACC_UA_GET_LE16)\n\treturn ACC_UA_GET_LE16(p);\n#    else\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\treturn ((unsigned)b[0]) | ((unsigned)b[1] << 8);\n#    endif\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_ua_get_le24) (const acc_hvoid_p p) {\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\treturn ((acc_uint32l_t) b[0]) | ((acc_uint32l_t) b[1] << 8) | ((acc_uint32l_t) b[2] << 16);\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_ua_get_le32) (const acc_hvoid_p p) {\n#    if defined(ACC_UA_GET_LE32)\n\treturn ACC_UA_GET_LE32(p);\n#    else\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\treturn ((acc_uint32l_t) b[0]) | ((acc_uint32l_t) b[1] << 8) | ((acc_uint32l_t) b[2] << 16) | ((acc_uint32l_t) b[3] << 24);\n#    endif\n}\n\nACCLIB_PUBLIC(void, acc_ua_set_le16)(acc_hvoid_p p, unsigned v) {\n#    if defined(ACC_UA_SET_LE16)\n\tACC_UA_SET_LE16(p, v);\n#    else\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tb[0] = (unsigned char)((v >> 0) & 0xff);\n\tb[1] = (unsigned char)((v >> 8) & 0xff);\n#    endif\n}\n\nACCLIB_PUBLIC(void, acc_ua_set_le24) (acc_hvoid_p p, acc_uint32l_t v) {\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tb[0] = (unsigned char)((v >> 0) & 0xff);\n\tb[1] = (unsigned char)((v >> 8) & 0xff);\n\tb[2] = (unsigned char)((v >> 16) & 0xff);\n}\n\nACCLIB_PUBLIC(void, acc_ua_set_le32) (acc_hvoid_p p, acc_uint32l_t v) {\n#    if defined(ACC_UA_SET_LE32)\n\tACC_UA_SET_LE32(p, v);\n#    else\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tb[0] = (unsigned char)((v >> 0) & 0xff);\n\tb[1] = (unsigned char)((v >> 8) & 0xff);\n\tb[2] = (unsigned char)((v >> 16) & 0xff);\n\tb[3] = (unsigned char)((v >> 24) & 0xff);\n#    endif\n}\n\n#    if defined(acc_int64l_t)\nACCLIB_PUBLIC(acc_uint64l_t, acc_ua_get_be64) (const acc_hvoid_p p) {\n#        if defined(ACC_UA_GET_BE64)\n\treturn ACC_UA_GET_BE64(p);\n#        elif defined(ACC_UA_GET_BE32)\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\tacc_uint32e_t v0, v1;\n\tv1 = ACC_UA_GET_BE32(b + 0);\n\tv0 = ACC_UA_GET_BE32(b + 4);\n\treturn ((acc_uint64l_t) v0) | ((acc_uint64l_t) v1 << 32);\n#        elif (ACC_SIZEOF_LONG >= 8) || (ACC_SIZEOF_SIZE_T >= 8)\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\treturn ((acc_uint64l_t) b[7]) | ((acc_uint64l_t) b[6] << 8) | ((acc_uint64l_t) b[5] << 16) | ((acc_uint64l_t) b[4] << 24) | ((acc_uint64l_t) b[3] << 32) | ((acc_uint64l_t) b[2] << 40) | ((acc_uint64l_t) b[1] << 48) | ((acc_uint64l_t) b[0] << 56);\n#        else\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\tacc_uint32l_t v0, v1;\n\tv1 = ((acc_uint32l_t) b[3]) | ((acc_uint32l_t) b[2] << 8) | ((acc_uint32l_t) b[1] << 16) | ((acc_uint32l_t) b[0] << 24);\n\tb += 4;\n\tv0 = ((acc_uint32l_t) b[3]) | ((acc_uint32l_t) b[2] << 8) | ((acc_uint32l_t) b[1] << 16) | ((acc_uint32l_t) b[0] << 24);\n\treturn ((acc_uint64l_t) v0) | ((acc_uint64l_t) v1 << 32);\n#        endif\n}\n\nACCLIB_PUBLIC(void, acc_ua_set_be64)(acc_hvoid_p p, acc_uint64l_t v) {\n#        if defined(ACC_UA_SET_BE64)\n\tACC_UA_SET_BE64(p, v);\n#        elif defined(ACC_UA_SET_BE32)\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tACC_UA_SET_BE32(b + 4, (v >> 0));\n\tACC_UA_SET_BE32(b + 0, (v >> 32));\n#        elif (ACC_SIZEOF_LONG >= 8) || (ACC_SIZEOF_SIZE_T >= 8)\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tb[7] = (unsigned char)((v >> 0) & 0xff);\n\tb[6] = (unsigned char)((v >> 8) & 0xff);\n\tb[5] = (unsigned char)((v >> 16) & 0xff);\n\tb[4] = (unsigned char)((v >> 24) & 0xff);\n\tb[3] = (unsigned char)((v >> 32) & 0xff);\n\tb[2] = (unsigned char)((v >> 40) & 0xff);\n\tb[1] = (unsigned char)((v >> 48) & 0xff);\n\tb[0] = (unsigned char)((v >> 56) & 0xff);\n#        else\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tacc_uint32l_t x;\n\tx = (acc_uint32l_t) (v >> 0);\n\tb[7] = (unsigned char)((x >> 0) & 0xff);\n\tb[6] = (unsigned char)((x >> 8) & 0xff);\n\tb[5] = (unsigned char)((x >> 16) & 0xff);\n\tb[4] = (unsigned char)((x >> 24) & 0xff);\n\tx = (acc_uint32l_t) (v >> 32);\n\tb[3] = (unsigned char)((x >> 0) & 0xff);\n\tb[2] = (unsigned char)((x >> 8) & 0xff);\n\tb[1] = (unsigned char)((x >> 16) & 0xff);\n\tb[0] = (unsigned char)((x >> 24) & 0xff);\n#        endif\n}\n#    endif\n#    if defined(acc_int64l_t)\nACCLIB_PUBLIC(acc_uint64l_t, acc_ua_get_le64) (const acc_hvoid_p p) {\n#        if defined(ACC_UA_GET_LE64)\n\treturn ACC_UA_GET_LE64(p);\n#        elif defined(ACC_UA_GET_LE32)\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\tacc_uint32e_t v0, v1;\n\tv0 = ACC_UA_GET_LE32(b + 0);\n\tv1 = ACC_UA_GET_LE32(b + 4);\n\treturn ((acc_uint64l_t) v0) | ((acc_uint64l_t) v1 << 32);\n#        elif (ACC_SIZEOF_LONG >= 8) || (ACC_SIZEOF_SIZE_T >= 8)\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\treturn ((acc_uint64l_t) b[0]) | ((acc_uint64l_t) b[1] << 8) | ((acc_uint64l_t) b[2] << 16) | ((acc_uint64l_t) b[3] << 24) | ((acc_uint64l_t) b[4] << 32) | ((acc_uint64l_t) b[5] << 40) | ((acc_uint64l_t) b[6] << 48) | ((acc_uint64l_t) b[7] << 56);\n#        else\n\tconst acc_hbyte_p b = (const acc_hbyte_p)p;\n\tacc_uint32l_t v0, v1;\n\tv0 = ((acc_uint32l_t) b[0]) | ((acc_uint32l_t) b[1] << 8) | ((acc_uint32l_t) b[2] << 16) | ((acc_uint32l_t) b[3] << 24);\n\tb += 4;\n\tv1 = ((acc_uint32l_t) b[0]) | ((acc_uint32l_t) b[1] << 8) | ((acc_uint32l_t) b[2] << 16) | ((acc_uint32l_t) b[3] << 24);\n\treturn ((acc_uint64l_t) v0) | ((acc_uint64l_t) v1 << 32);\n#        endif\n}\n\nACCLIB_PUBLIC(void, acc_ua_set_le64)(acc_hvoid_p p, acc_uint64l_t v) {\n#        if defined(ACC_UA_SET_LE64)\n\tACC_UA_SET_LE64(p, v);\n#        elif defined(ACC_UA_SET_LE32)\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tACC_UA_SET_LE32(b + 0, (v >> 0));\n\tACC_UA_SET_LE32(b + 4, (v >> 32));\n#        elif (ACC_SIZEOF_LONG >= 8) || (ACC_SIZEOF_SIZE_T >= 8)\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tb[0] = (unsigned char)((v >> 0) & 0xff);\n\tb[1] = (unsigned char)((v >> 8) & 0xff);\n\tb[2] = (unsigned char)((v >> 16) & 0xff);\n\tb[3] = (unsigned char)((v >> 24) & 0xff);\n\tb[4] = (unsigned char)((v >> 32) & 0xff);\n\tb[5] = (unsigned char)((v >> 40) & 0xff);\n\tb[6] = (unsigned char)((v >> 48) & 0xff);\n\tb[7] = (unsigned char)((v >> 56) & 0xff);\n#        else\n\tacc_hbyte_p b = (acc_hbyte_p) p;\n\tacc_uint32l_t x;\n\tx = (acc_uint32l_t) (v >> 0);\n\tb[0] = (unsigned char)((x >> 0) & 0xff);\n\tb[1] = (unsigned char)((x >> 8) & 0xff);\n\tb[2] = (unsigned char)((x >> 16) & 0xff);\n\tb[3] = (unsigned char)((x >> 24) & 0xff);\n\tx = (acc_uint32l_t) (v >> 32);\n\tb[4] = (unsigned char)((x >> 0) & 0xff);\n\tb[5] = (unsigned char)((x >> 8) & 0xff);\n\tb[6] = (unsigned char)((x >> 16) & 0xff);\n\tb[7] = (unsigned char)((x >> 24) & 0xff);\n#        endif\n}\n#    endif\n#endif\n#if defined(ACC_WANT_ACCLIB_VGET)\n#    undef ACC_WANT_ACCLIB_VGET\n#    define __ACCLIB_VGET_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)                r __ACCLIB_FUNCNAME(f)\n#    endif\n#    if !defined(ACCLIB_PUBLIC_NOINLINE)\n#        if !defined(__acc_noinline)\n#            define ACCLIB_PUBLIC_NOINLINE(r,f)     r __ACCLIB_FUNCNAME(f)\n#        elif (ACC_CC_GNUC >= 0x030400ul) || (ACC_CC_LLVM)\n#            define ACCLIB_PUBLIC_NOINLINE(r,f)     __acc_noinline __attribute__((__used__)) r __ACCLIB_FUNCNAME(f)\n#        else\n#            define ACCLIB_PUBLIC_NOINLINE(r,f)     __acc_noinline r __ACCLIB_FUNCNAME(f)\n#        endif\n#    endif\n#    if (ACC_CC_GNUC >= 0x030400ul) || (ACC_CC_LLVM)\nextern void *volatile __acc_vget_ptr;\nvoid *volatile __attribute__ ((__used__)) __acc_vget_ptr = (void *)0;\n#    else\nextern void *volatile __acc_vget_ptr;\nvoid *volatile __acc_vget_ptr = (void *)0;\n#    endif\n#    ifndef __ACCLIB_VGET_BODY\n#        define __ACCLIB_VGET_BODY(T) \\\n    if __acc_unlikely(__acc_vget_ptr) { \\\n        * (T *) __acc_vget_ptr = v; \\\n        * (int *) __acc_vget_ptr = expr; \\\n        v = * (T *) __acc_vget_ptr; \\\n    } \\\n    return v;\n#    endif\nACCLIB_PUBLIC_NOINLINE(short, acc_vget_short) (short v, int expr) {\n\t__ACCLIB_VGET_BODY(short)\n} ACCLIB_PUBLIC_NOINLINE(int, acc_vget_int) (int v, int expr) {\n\t__ACCLIB_VGET_BODY(int)\n} ACCLIB_PUBLIC_NOINLINE(long, acc_vget_long) (long v, int expr) {\n\t__ACCLIB_VGET_BODY(long)\n}\n#    if defined(acc_int64l_t)\nACCLIB_PUBLIC_NOINLINE(acc_int64l_t, acc_vget_acc_int64l_t) (acc_int64l_t v, int expr) {\n\t__ACCLIB_VGET_BODY(acc_int64l_t)\n}\n#    endif\nACCLIB_PUBLIC_NOINLINE(acc_hsize_t, acc_vget_acc_hsize_t) (acc_hsize_t v, int expr) {\n\t__ACCLIB_VGET_BODY(acc_hsize_t)\n}\n\n#    if !defined(ACC_CFG_NO_FLOAT)\nACCLIB_PUBLIC_NOINLINE(float, acc_vget_float) (float v, int expr) {\n\t__ACCLIB_VGET_BODY(float)\n}\n#    endif\n#    if !defined(ACC_CFG_NO_DOUBLE)\nACCLIB_PUBLIC_NOINLINE(double, acc_vget_double) (double v, int expr) {\n\t__ACCLIB_VGET_BODY(double)\n}\n#    endif\nACCLIB_PUBLIC_NOINLINE(acc_hvoid_p, acc_vget_acc_hvoid_p) (acc_hvoid_p v, int expr) {\n\t__ACCLIB_VGET_BODY(acc_hvoid_p)\n}\n\n#    if (ACC_ARCH_I086 && ACC_CC_TURBOC && (__TURBOC__ == 0x0295)) && !defined(__cplusplus)\nACCLIB_PUBLIC_NOINLINE(acc_hvoid_p, acc_vget_acc_hvoid_cp) (const acc_hvoid_p vv, int expr) {\n\tacc_hvoid_p v = (acc_hvoid_p) vv;\n\t__ACCLIB_VGET_BODY(acc_hvoid_p)\n}\n#    else\nACCLIB_PUBLIC_NOINLINE(const acc_hvoid_p, acc_vget_acc_hvoid_cp) (const acc_hvoid_p v, int expr) {\n\t__ACCLIB_VGET_BODY(const acc_hvoid_p)\n}\n#    endif\n#endif\n#if defined(ACC_WANT_ACCLIB_HMEMCPY)\n#    undef ACC_WANT_ACCLIB_HMEMCPY\n#    define __ACCLIB_HMEMCPY_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\nACCLIB_PUBLIC(int, acc_hmemcmp) (const acc_hvoid_p s1, const acc_hvoid_p s2, acc_hsize_t len) {\n#    if (ACC_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCMP)\n\tconst acc_hbyte_p p1 = (const acc_hbyte_p)s1;\n\tconst acc_hbyte_p p2 = (const acc_hbyte_p)s2;\n\tif __acc_likely\n\t\t(len > 0)\n\t\tdo {\n\t\t\tint d = *p1 - *p2;\n\t\t\tif (d != 0)\n\t\t\t\treturn d;\n\t\t\tp1++;\n\t\t\tp2++;\n\t\t} while __acc_likely\n\t\t(--len > 0);\n\treturn 0;\n#    else\n\treturn memcmp(s1, s2, len);\n#    endif\n}\n\nACCLIB_PUBLIC(acc_hvoid_p, acc_hmemcpy) (acc_hvoid_p dest, const acc_hvoid_p src, acc_hsize_t len) {\n#    if (ACC_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCPY)\n\tacc_hbyte_p p1 = (acc_hbyte_p) dest;\n\tconst acc_hbyte_p p2 = (const acc_hbyte_p)src;\n\tif (!(len > 0) || p1 == p2)\n\t\treturn dest;\n\tdo\n\t\t*p1++ = *p2++;\n\twhile __acc_likely\n\t(--len > 0);\n\treturn dest;\n#    else\n\treturn memcpy(dest, src, len);\n#    endif\n}\n\nACCLIB_PUBLIC(acc_hvoid_p, acc_hmemmove) (acc_hvoid_p dest, const acc_hvoid_p src, acc_hsize_t len) {\n#    if (ACC_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMMOVE)\n\tacc_hbyte_p p1 = (acc_hbyte_p) dest;\n\tconst acc_hbyte_p p2 = (const acc_hbyte_p)src;\n\tif (!(len > 0) || p1 == p2)\n\t\treturn dest;\n\tif (p1 < p2) {\n\t\tdo\n\t\t\t*p1++ = *p2++;\n\t\twhile __acc_likely\n\t\t(--len > 0);\n\t} else {\n\t\tp1 += len;\n\t\tp2 += len;\n\t\tdo\n\t\t\t*--p1 = *--p2;\n\t\twhile __acc_likely\n\t\t(--len > 0);\n\t}\n\treturn dest;\n#    else\n\treturn memmove(dest, src, len);\n#    endif\n}\n\nACCLIB_PUBLIC(acc_hvoid_p, acc_hmemset) (acc_hvoid_p s, int c, acc_hsize_t len) {\n#    if (ACC_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMSET)\n\tacc_hbyte_p p = (acc_hbyte_p) s;\n\tif __acc_likely\n\t\t(len > 0)\n\t\tdo\n\t\t\t*p++ = (unsigned char)c;\n\t\twhile __acc_likely\n\t\t(--len > 0);\n\treturn s;\n#    else\n\treturn memset(s, c, len);\n#    endif\n}\n#endif\n#if defined(ACC_WANT_ACCLIB_RAND)\n#    undef ACC_WANT_ACCLIB_RAND\n#    define __ACCLIB_RAND_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\nACCLIB_PUBLIC(void, acc_srand31)(acc_rand31_p r, acc_uint32l_t seed) {\n\tr->seed = seed & ACC_UINT32_C(0xffffffff);\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_rand31) (acc_rand31_p r) {\n\tr->seed = r->seed * ACC_UINT32_C(1103515245) + 12345;\n\tr->seed &= ACC_UINT32_C(0x7fffffff);\n\treturn r->seed;\n}\n\n#    if defined(acc_int64l_t)\nACCLIB_PUBLIC(void, acc_srand48)(acc_rand48_p r, acc_uint32l_t seed) {\n\tr->seed = seed & ACC_UINT32_C(0xffffffff);\n\tr->seed <<= 16;\n\tr->seed |= 0x330e;\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_rand48) (acc_rand48_p r) {\n\tr->seed = r->seed * ACC_UINT64_C(25214903917) + 11;\n\tr->seed &= ACC_UINT64_C(0xffffffffffff);\n\treturn (acc_uint32l_t) (r->seed >> 17);\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_rand48_r32) (acc_rand48_p r) {\n\tr->seed = r->seed * ACC_UINT64_C(25214903917) + 11;\n\tr->seed &= ACC_UINT64_C(0xffffffffffff);\n\treturn (acc_uint32l_t) (r->seed >> 16);\n}\n#    endif\n#    if defined(acc_int64l_t)\nACCLIB_PUBLIC(void, acc_srand64)(acc_rand64_p r, acc_uint64l_t seed) {\n\tr->seed = seed & ACC_UINT64_C(0xffffffffffffffff);\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_rand64) (acc_rand64_p r) {\n\tr->seed = r->seed * ACC_UINT64_C(6364136223846793005) + 1;\n#        if (ACC_SIZEOF_ACC_INT64L_T > 8)\n\tr->seed &= ACC_UINT64_C(0xffffffffffffffff);\n#        endif\n\treturn (acc_uint32l_t) (r->seed >> 33);\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_rand64_r32) (acc_rand64_p r) {\n\tr->seed = r->seed * ACC_UINT64_C(6364136223846793005) + 1;\n#        if (ACC_SIZEOF_ACC_INT64L_T > 8)\n\tr->seed &= ACC_UINT64_C(0xffffffffffffffff);\n#        endif\n\treturn (acc_uint32l_t) (r->seed >> 32);\n}\n#    endif\nACCLIB_PUBLIC(void, acc_srandmt)(acc_randmt_p r, acc_uint32l_t seed) {\n\tunsigned i = 0;\n\tdo {\n\t\tr->s[i++] = (seed &= ACC_UINT32_C(0xffffffff));\n\t\tseed ^= seed >> 30;\n\t\tseed = seed * ACC_UINT32_C(0x6c078965) + i;\n\t} while (i != 624);\n\tr->n = i;\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_randmt) (acc_randmt_p r) {\n\treturn (__ACCLIB_FUNCNAME(acc_randmt_r32) (r)) >> 1;\n}\n\nACCLIB_PUBLIC(acc_uint32l_t, acc_randmt_r32) (acc_randmt_p r) {\n\tacc_uint32l_t v;\n\tif __acc_unlikely\n\t\t(r->n == 624) {\n\t\tint i = 0, j;\n\t\tr->n = 0;\n\t\tdo {\n\t\t\tj = i - 623;\n\t\t\tif (j < 0)\n\t\t\t\tj += 624;\n\t\t\tv = (r->s[i] & ACC_UINT32_C(0x80000000)) ^ (r->s[j] & ACC_UINT32_C(0x7fffffff));\n\t\t\tj = i - 227;\n\t\t\tif (j < 0)\n\t\t\t\tj += 624;\n\t\t\tr->s[i] = r->s[j] ^ (v >> 1);\n\t\t\tif (v & 1)\n\t\t\t\tr->s[i] ^= ACC_UINT32_C(0x9908b0df);\n\t\t} while (++i != 624);\n\t\t}\n\tv = r->s[r->n++];\n\tv ^= v >> 11;\n\tv ^= (v & ACC_UINT32_C(0x013a58ad)) << 7;\n\tv ^= (v & ACC_UINT32_C(0x0001df8c)) << 15;\n\tv ^= v >> 18;\n\treturn v;\n}\n\n#    if defined(acc_int64l_t)\nACCLIB_PUBLIC(void, acc_srandmt64)(acc_randmt64_p r, acc_uint64l_t seed) {\n\tunsigned i = 0;\n\tdo {\n\t\tr->s[i++] = (seed &= ACC_UINT64_C(0xffffffffffffffff));\n\t\tseed ^= seed >> 62;\n\t\tseed = seed * ACC_UINT64_C(0x5851f42d4c957f2d) + i;\n\t} while (i != 312);\n\tr->n = i;\n}\n\n#        if 0\nACCLIB_PUBLIC(acc_uint32l_t, acc_randmt64) (acc_randmt64_p r) {\n\tacc_uint64l_t v;\n\tv = (__ACCLIB_FUNCNAME(acc_randmt64_r64) (r)) >> 33;\n\treturn (acc_uint32l_t) v;\n}\n#        endif\nACCLIB_PUBLIC(acc_uint64l_t, acc_randmt64_r64) (acc_randmt64_p r) {\n\tacc_uint64l_t v;\n\tif __acc_unlikely\n\t\t(r->n == 312) {\n\t\tint i = 0, j;\n\t\tr->n = 0;\n\t\tdo {\n\t\t\tj = i - 311;\n\t\t\tif (j < 0)\n\t\t\t\tj += 312;\n\t\t\tv = (r->s[i] & ACC_UINT64_C(0xffffffff80000000)) ^ (r->s[j] & ACC_UINT64_C(0x7fffffff));\n\t\t\tj = i - 156;\n\t\t\tif (j < 0)\n\t\t\t\tj += 312;\n\t\t\tr->s[i] = r->s[j] ^ (v >> 1);\n\t\t\tif (v & 1)\n\t\t\t\tr->s[i] ^= ACC_UINT64_C(0xb5026f5aa96619e9);\n\t\t} while (++i != 312);\n\t\t}\n\tv = r->s[r->n++];\n\tv ^= (v & ACC_UINT64_C(0xaaaaaaaaa0000000)) >> 29;\n\tv ^= (v & ACC_UINT64_C(0x38eb3ffff6d3)) << 17;\n\tv ^= (v & ACC_UINT64_C(0x7ffbf77)) << 37;\n\treturn v ^ (v >> 43);\n}\n#    endif\n#endif\n#if defined(ACC_WANT_ACCLIB_RDTSC)\n#    undef ACC_WANT_ACCLIB_RDTSC\n#    define __ACCLIB_RDTSC_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\n#    if defined(acc_int32e_t)\n#        if (ACC_OS_WIN32 && ACC_CC_PELLESC && (__POCC__ >= 290))\n#            pragma warn(push)\n#            pragma warn(disable:2007)\n#        endif\n#        if (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)\n#            if (ACC_ARCH_AMD64 && ACC_CC_PATHSCALE)\n#                define __ACCLIB_RDTSC_REGS   : : \"c\" (t) : \"cc\", \"memory\", \"rax\", \"rdx\"\n#            elif (ACC_ARCH_AMD64 && ACC_CC_INTELC)\n#                define __ACCLIB_RDTSC_REGS   : : \"r\" (t) : \"memory\", \"rax\", \"rdx\"\n#            elif (ACC_ARCH_AMD64)\n#                define __ACCLIB_RDTSC_REGS   : : \"r\" (t) : \"cc\", \"memory\", \"rax\", \"rdx\"\n#            elif (ACC_ARCH_I386 && ACC_CC_GNUC && (ACC_CC_GNUC < 0x020000ul))\n#                define __ACCLIB_RDTSC_REGS   : : \"r\" (t) : \"ax\", \"dx\"\n#            elif (ACC_ARCH_I386 && ACC_CC_INTELC)\n#                define __ACCLIB_RDTSC_REGS   : : \"r\" (t) : \"memory\", \"eax\", \"edx\"\n#            elif (ACC_ARCH_I386 && ACC_CC_PATHSCALE)\n#                define __ACCLIB_RDTSC_REGS   : : \"c\" (t) : \"memory\", \"eax\", \"edx\"\n#            else\n#                define __ACCLIB_RDTSC_REGS   : : \"r\" (t) : \"cc\", \"memory\", \"eax\", \"edx\"\n#            endif\n#        endif\nACCLIB_PUBLIC(int, acc_tsc_read)(acc_uint32e_t * t) {\n#        if (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)\n\t__asm__ __volatile__(\"clc \\n\" \".byte 0x0f,0x31\\n\" \"movl %%eax,(%0)\\n\" \"movl %%edx,4(%0)\\n\" __ACCLIB_RDTSC_REGS);\n\treturn 0;\n#        elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_MSC)\n\tACC_UNUSED(t);\n\t__asm {\n\t\tmov ecx, t clc\n#            if (ACC_CC_MSC && (_MSC_VER < 1200))\n\t\t _emit 0x0f _emit 0x31\n#            else\n\t\t rdtsc\n#            endif\n\t mov[ecx], eax mov[ecx + 4], edx} return 0;\n#        else\n\tt[0] = t[1] = 0;\n\treturn -1;\n#        endif\n}\n\n#        if (ACC_OS_WIN32 && ACC_CC_PELLESC && (__POCC__ >= 290))\n#            pragma warn(pop)\n#        endif\n#    endif\n#endif\n#if defined(ACC_WANT_ACCLIB_DOSALLOC)\n#    undef ACC_WANT_ACCLIB_DOSALLOC\n#    define __ACCLIB_DOSALLOC_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\n#    if (ACC_OS_OS216)\nACC_EXTERN_C unsigned short __far __pascal DosAllocHuge(unsigned short, unsigned short, unsigned short __far *, unsigned short, unsigned short);\nACC_EXTERN_C unsigned short __far __pascal DosFreeSeg(unsigned short);\n#    endif\n#    if (ACC_OS_DOS16 || ACC_OS_WIN16)\n#        if !defined(ACC_CC_AZTECC)\nACCLIB_PUBLIC(void __far *, acc_dos_alloc) (unsigned long size) {\n\tvoid __far *p = 0;\n\tunion REGS ri, ro;\n\tif ((long)size <= 0)\n\t\treturn p;\n\tsize = (size + 15) >> 4;\n\tif (size > 0xffffu)\n\t\treturn p;\n\tri.x.ax = 0x4800;\n\tri.x.bx = (unsigned short)size;\n\tint86(0x21, &ri, &ro);\n\tif ((ro.x.cflag & 1) == 0)\n\t\tp = (void __far *)ACC_PTR_MK_FP(ro.x.ax, 0);\n\treturn p;\n}\n\nACCLIB_PUBLIC(int, acc_dos_free)(void __far * p) {\n\tunion REGS ri, ro;\n\tstruct SREGS rs;\n\tif (!p)\n\t\treturn 0;\n\tif (ACC_PTR_FP_OFF(p) != 0)\n\t\treturn -1;\n\tsegread(&rs);\n\tri.x.ax = 0x4900;\n\trs.es = ACC_PTR_FP_SEG(p);\n\tint86x(0x21, &ri, &ro, &rs);\n\tif (ro.x.cflag & 1)\n\t\treturn -1;\n\treturn 0;\n}\n#        endif\n#    endif\n#    if (ACC_OS_OS216)\nACCLIB_PUBLIC(void __far *, acc_dos_alloc)(unsigned long size) {\n\tvoid __far *p = 0;\n\tunsigned short sel = 0;\n\tif ((long)size <= 0)\n\t\treturn p;\n\tif (DosAllocHuge((unsigned short)(size >> 16), (unsigned short)size, &sel, 0, 0) == 0)\n\t\tp = (void __far *)ACC_PTR_MK_FP(sel, 0);\n\treturn p;\n}\n\nACCLIB_PUBLIC(int, acc_dos_free)(void __far * p) {\n\tif (!p)\n\t\treturn 0;\n\tif (ACC_PTR_FP_OFF(p) != 0)\n\t\treturn -1;\n\tif (DosFreeSeg(ACC_PTR_FP_SEG(p)) != 0)\n\t\treturn -1;\n\treturn 0;\n}\n#    endif\n#endif\n#if defined(ACC_WANT_ACCLIB_HALLOC)\n#    undef ACC_WANT_ACCLIB_HALLOC\n#    define __ACCLIB_HALLOC_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\n#    if (ACC_HAVE_MM_HUGE_PTR)\n#        if 1 && (ACC_OS_DOS16 && defined(BLX286))\n#            define __ACCLIB_HALLOC_USE_DAH 1\n#        elif 1 && (ACC_OS_DOS16 && defined(DOSX286))\n#            define __ACCLIB_HALLOC_USE_DAH 1\n#        elif 1 && (ACC_OS_OS216)\n#            define __ACCLIB_HALLOC_USE_DAH 1\n#        elif 1 && (ACC_OS_WIN16)\n#            define __ACCLIB_HALLOC_USE_GA 1\n#        elif 1 && (ACC_OS_DOS16) && (ACC_CC_BORLANDC) && defined(__DPMI16__)\n#            define __ACCLIB_HALLOC_USE_GA 1\n#        endif\n#    endif\n#    if (__ACCLIB_HALLOC_USE_DAH)\n#        if 0 && (ACC_OS_OS216)\n#            include <os2.h>\n#        else\nACC_EXTERN_C unsigned short __far __pascal DosAllocHuge(unsigned short, unsigned short, unsigned short __far *, unsigned short, unsigned short);\nACC_EXTERN_C unsigned short __far __pascal DosFreeSeg(unsigned short);\n#        endif\n#    endif\n#    if (__ACCLIB_HALLOC_USE_GA)\n#        if 0\n#            define STRICT 1\n#            include <windows.h>\n#        else\nACC_EXTERN_C const void __near *__far __pascal GlobalAlloc(unsigned, unsigned long);\nACC_EXTERN_C const void __near *__far __pascal GlobalFree(const void __near *);\nACC_EXTERN_C unsigned long __far __pascal GlobalHandle(unsigned);\nACC_EXTERN_C void __far *__far __pascal GlobalLock(const void __near *);\nACC_EXTERN_C int __far __pascal GlobalUnlock(const void __near *);\n#        endif\n#    endif\nACCLIB_PUBLIC(acc_hvoid_p, acc_halloc) (acc_hsize_t size) {\n\tacc_hvoid_p p = 0;\n\tif (!(size > 0))\n\t\treturn p;\n#    if 0 && defined(__palmos__)\n\tp = MemPtrNew(size);\n#    elif !defined(ACC_HAVE_MM_HUGE_PTR)\n\tif (size < (size_t) - 1)\n\t\tp = malloc((size_t) size);\n#    else\n\tif ((long)size <= 0)\n\t\treturn p;\n\t{\n#        if (__ACCLIB_HALLOC_USE_DAH)\n\t\tunsigned short sel = 0;\n\t\tif (DosAllocHuge((unsigned short)(size >> 16), (unsigned short)size, &sel, 0, 0) == 0)\n\t\t\tp = (acc_hvoid_p) ACC_PTR_MK_FP(sel, 0);\n#        elif (__ACCLIB_HALLOC_USE_GA)\n\t\tconst void __near *h = GlobalAlloc(2, size);\n\t\tif (h) {\n\t\t\tp = GlobalLock(h);\n\t\t\tif (p && ACC_PTR_FP_OFF(p) != 0) {\n\t\t\t\tGlobalUnlock(h);\n\t\t\t\tp = 0;\n\t\t\t}\n\t\t\tif (!p)\n\t\t\t\tGlobalFree(h);\n\t\t}\n#        elif (ACC_CC_MSC && (_MSC_VER >= 700))\n\t\tp = _halloc(size, 1);\n#        elif (ACC_CC_MSC || ACC_CC_WATCOMC)\n\t\tp = halloc(size, 1);\n#        elif (ACC_CC_DMC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)\n\t\tp = farmalloc(size);\n#        elif (ACC_CC_BORLANDC || ACC_CC_TURBOC)\n\t\tp = farmalloc(size);\n#        elif defined(ACC_CC_AZTECC)\n\t\tp = lmalloc(size);\n#        else\n\t\tif (size < (size_t) - 1)\n\t\t\tp = malloc((size_t) size);\n#        endif\n\t}\n#    endif\n\treturn p;\n}\n\nACCLIB_PUBLIC(void, acc_hfree)(acc_hvoid_p p) {\n\tif (!p)\n\t\treturn;\n#    if 0 && defined(__palmos__)\n\tMemPtrFree(p);\n#    elif !defined(ACC_HAVE_MM_HUGE_PTR)\n\tfree(p);\n#    else\n#        if (__ACCLIB_HALLOC_USE_DAH)\n\tif (ACC_PTR_FP_OFF(p) == 0)\n\t\tDosFreeSeg((unsigned short)ACC_PTR_FP_SEG(p));\n#        elif (__ACCLIB_HALLOC_USE_GA)\n\tif (ACC_PTR_FP_OFF(p) == 0) {\n\t\tconst void __near *h = (const void __near *)(unsigned)GlobalHandle(ACC_PTR_FP_SEG(p));\n\t\tif (h) {\n\t\t\tGlobalUnlock(h);\n\t\t\tGlobalFree(h);\n\t\t}\n\t}\n#        elif (ACC_CC_MSC && (_MSC_VER >= 700))\n\t_hfree(p);\n#        elif (ACC_CC_MSC || ACC_CC_WATCOMC)\n\thfree(p);\n#        elif (ACC_CC_DMC || ACC_CC_SYMANTECC || ACC_CC_ZORTECHC)\n\tfarfree((void __far *)p);\n#        elif (ACC_CC_BORLANDC || ACC_CC_TURBOC)\n\tfarfree((void __far *)p);\n#        elif defined(ACC_CC_AZTECC)\n\tlfree(p);\n#        else\n\tfree(p);\n#        endif\n#    endif\n}\n#endif\n#if defined(ACC_WANT_ACCLIB_HFREAD)\n#    undef ACC_WANT_ACCLIB_HFREAD\n#    define __ACCLIB_HFREAD_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\nACCLIB_PUBLIC(acc_hsize_t, acc_hfread) (void *vfp, acc_hvoid_p buf, acc_hsize_t size) {\n\tFILE *fp = (FILE *) vfp;\n#    if (ACC_HAVE_MM_HUGE_PTR)\n#        if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)\n#            define __ACCLIB_REQUIRE_HMEMCPY_CH 1\n\tunsigned char tmp[512];\n\tacc_hsize_t l = 0;\n\twhile (l < size) {\n\t\tsize_t n = size - l > sizeof(tmp) ? sizeof(tmp) : (size_t) (size - l);\n\t\tn = fread(tmp, 1, n, fp);\n\t\tif (n == 0)\n\t\t\tbreak;\n\t\t__ACCLIB_FUNCNAME(acc_hmemcpy) ((acc_hbyte_p) buf + l, tmp, (acc_hsize_t) n);\n\t\tl += n;\n\t}\n\treturn l;\n#        elif (ACC_MM_COMPACT || ACC_MM_LARGE || ACC_MM_HUGE)\n\tacc_hbyte_p b = (acc_hbyte_p) buf;\n\tacc_hsize_t l = 0;\n\twhile (l < size) {\n\t\tsize_t n;\n\t\tn = ACC_PTR_FP_OFF(b);\n\t\tn = (n <= 1) ? 0x8000u : (0u - n);\n\t\tif ((acc_hsize_t) n > size - l)\n\t\t\tn = (size_t) (size - l);\n\t\tn = fread((void __far *)b, 1, n, fp);\n\t\tif (n == 0)\n\t\t\tbreak;\n\t\tb += n;\n\t\tl += n;\n\t}\n\treturn l;\n#        else\n#            error \"unknown memory model\"\n#        endif\n#    else\n\treturn fread(buf, 1, size, fp);\n#    endif\n}\n\nACCLIB_PUBLIC(acc_hsize_t, acc_hfwrite) (void *vfp, const acc_hvoid_p buf, acc_hsize_t size) {\n\tFILE *fp = (FILE *) vfp;\n#    if (ACC_HAVE_MM_HUGE_PTR)\n#        if (ACC_MM_TINY || ACC_MM_SMALL || ACC_MM_MEDIUM)\n#            define __ACCLIB_REQUIRE_HMEMCPY_CH 1\n\tunsigned char tmp[512];\n\tacc_hsize_t l = 0;\n\twhile (l < size) {\n\t\tsize_t n = size - l > sizeof(tmp) ? sizeof(tmp) : (size_t) (size - l);\n\t\t__ACCLIB_FUNCNAME(acc_hmemcpy) (tmp, (const acc_hbyte_p)buf + l, (acc_hsize_t) n);\n\t\tn = fwrite(tmp, 1, n, fp);\n\t\tif (n == 0)\n\t\t\tbreak;\n\t\tl += n;\n\t}\n\treturn l;\n#        elif (ACC_MM_COMPACT || ACC_MM_LARGE || ACC_MM_HUGE)\n\tconst acc_hbyte_p b = (const acc_hbyte_p)buf;\n\tacc_hsize_t l = 0;\n\twhile (l < size) {\n\t\tsize_t n;\n\t\tn = ACC_PTR_FP_OFF(b);\n\t\tn = (n <= 1) ? 0x8000u : (0u - n);\n\t\tif ((acc_hsize_t) n > size - l)\n\t\t\tn = (size_t) (size - l);\n\t\tn = fwrite((void __far *)b, 1, n, fp);\n\t\tif (n == 0)\n\t\t\tbreak;\n\t\tb += n;\n\t\tl += n;\n\t}\n\treturn l;\n#        else\n#            error \"unknown memory model\"\n#        endif\n#    else\n\treturn fwrite(buf, 1, size, fp);\n#    endif\n}\n#endif\n#if defined(ACC_WANT_ACCLIB_HSREAD)\n#    undef ACC_WANT_ACCLIB_HSREAD\n#    define __ACCLIB_HSREAD_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\nACCLIB_PUBLIC(long, acc_safe_hread)(int fd, acc_hvoid_p buf, long size) {\n\tacc_hbyte_p b = (acc_hbyte_p) buf;\n\tlong l = 0;\n\tint saved_errno;\n\tsaved_errno = errno;\n\twhile (l < size) {\n\t\tlong n = size - l;\n#    if (ACC_HAVE_MM_HUGE_PTR)\n#        define __ACCLIB_REQUIRE_HREAD_CH 1\n\t\terrno = 0;\n\t\tn = acc_hread(fd, b, n);\n#    elif (ACC_OS_DOS32) && defined(__DJGPP__)\n\t\terrno = 0;\n\t\tn = _read(fd, b, n);\n#    else\n\t\terrno = 0;\n\t\tn = read(fd, b, n);\n#    endif\n\t\tif (n == 0)\n\t\t\tbreak;\n\t\tif (n < 0) {\n#    if defined(EAGAIN)\n\t\t\tif (errno == (EAGAIN))\n\t\t\t\tcontinue;\n#    endif\n#    if defined(EINTR)\n\t\t\tif (errno == (EINTR))\n\t\t\t\tcontinue;\n#    endif\n\t\t\tif (errno == 0)\n\t\t\t\terrno = 1;\n\t\t\treturn l;\n\t\t}\n\t\tb += n;\n\t\tl += n;\n\t}\n\terrno = saved_errno;\n\treturn l;\n}\n\nACCLIB_PUBLIC(long, acc_safe_hwrite)(int fd, const acc_hvoid_p buf, long size) {\n\tconst acc_hbyte_p b = (const acc_hbyte_p)buf;\n\tlong l = 0;\n\tint saved_errno;\n\tsaved_errno = errno;\n\twhile (l < size) {\n\t\tlong n = size - l;\n#    if (ACC_HAVE_MM_HUGE_PTR)\n#        define __ACCLIB_REQUIRE_HREAD_CH 1\n\t\terrno = 0;\n\t\tn = acc_hwrite(fd, b, n);\n#    elif (ACC_OS_DOS32) && defined(__DJGPP__)\n\t\terrno = 0;\n\t\tn = _write(fd, b, n);\n#    else\n\t\terrno = 0;\n\t\tn = write(fd, b, n);\n#    endif\n\t\tif (n == 0)\n\t\t\tbreak;\n\t\tif (n < 0) {\n#    if defined(EAGAIN)\n\t\t\tif (errno == (EAGAIN))\n\t\t\t\tcontinue;\n#    endif\n#    if defined(EINTR)\n\t\t\tif (errno == (EINTR))\n\t\t\t\tcontinue;\n#    endif\n\t\t\tif (errno == 0)\n\t\t\t\terrno = 1;\n\t\t\treturn l;\n\t\t}\n\t\tb += n;\n\t\tl += n;\n\t}\n\terrno = saved_errno;\n\treturn l;\n}\n#endif\n#if defined(ACC_WANT_ACCLIB_PCLOCK)\n#    undef ACC_WANT_ACCLIB_PCLOCK\n#    define __ACCLIB_PCLOCK_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\n#    if defined(HAVE_GETTIMEOFDAY)\n#        ifndef acc_pclock_read_gettimeofday\n#            define acc_pclock_read_gettimeofday acc_pclock_read_gettimeofday\n#        endif\nstatic int acc_pclock_read_gettimeofday(acc_pclock_handle_p h, acc_pclock_p c) {\n\tstruct timeval tv;\n\tif (gettimeofday(&tv, 0) != 0)\n\t\treturn -1;\n#        if defined(acc_int64l_t)\n\tc->tv_sec = tv.tv_sec;\n#        else\n\tc->tv_sec_high = 0;\n\tc->tv_sec_low = tv.tv_sec;\n#        endif\n\tc->tv_nsec = (acc_uint32l_t) (tv.tv_usec * 1000u);\n\tACC_UNUSED(h);\n\treturn 0;\n}\n#    endif\n#    if defined(CLOCKS_PER_SEC)\n#        ifndef acc_pclock_read_clock\n#            define acc_pclock_read_clock acc_pclock_read_clock\n#        endif\nstatic int acc_pclock_read_clock(acc_pclock_handle_p h, acc_pclock_p c) {\n\tclock_t ticks;\n\tdouble secs;\n#        if defined(acc_int64l_t)\n\tacc_uint64l_t nsecs;\n\tticks = clock();\n\tsecs = (double)ticks / (CLOCKS_PER_SEC);\n\tnsecs = (acc_uint64l_t) (secs * 1000000000.0);\n\tc->tv_sec = (acc_int64l_t) (nsecs / 1000000000ul);\n\tc->tv_nsec = (acc_uint32l_t) (nsecs % 1000000000ul);\n#        else\n\tticks = clock();\n\tsecs = (double)ticks / (CLOCKS_PER_SEC);\n\tc->tv_sec_high = 0;\n\tc->tv_sec_low = (acc_uint32l_t) (secs + 0.5);\n\tc->tv_nsec = 0;\n#        endif\n\tACC_UNUSED(h);\n\treturn 0;\n}\n#    endif\n#    if (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__) && defined(UCLOCKS_PER_SEC)\n#        ifndef acc_pclock_read_uclock\n#            define acc_pclock_read_uclock acc_pclock_read_uclock\n#        endif\nstatic int acc_pclock_read_uclock(acc_pclock_handle_p h, acc_pclock_p c) {\n\tacc_uint64l_t ticks;\n\tdouble secs;\n\tacc_uint64l_t nsecs;\n\tticks = uclock();\n\tsecs = (double)ticks / (UCLOCKS_PER_SEC);\n\tnsecs = (acc_uint64l_t) (secs * 1000000000.0);\n\tc->tv_sec = nsecs / 1000000000ul;\n\tc->tv_nsec = (acc_uint32l_t) (nsecs % 1000000000ul);\n\tACC_UNUSED(h);\n\treturn 0;\n}\n#    endif\n#    if 0 && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) && defined(acc_int64l_t)\n#        ifndef acc_pclock_read_clock_gettime_p\n#            define acc_pclock_read_clock_gettime_p acc_pclock_read_clock_gettime_p\n#        endif\nstatic int acc_pclock_read_clock_gettime_p(acc_pclock_handle_p h, acc_pclock_p c) {\n\tstruct timespec ts;\n\tif (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) != 0)\n\t\treturn -1;\n\tc->tv_sec = ts.tv_sec;\n\tc->tv_nsec = ts.tv_nsec;\n\tACC_UNUSED(h);\n\treturn 0;\n}\n#    endif\n#    if (ACC_OS_CYGWIN || ACC_OS_WIN32 || ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H) && defined(acc_int64l_t)\n#        ifndef acc_pclock_read_getprocesstimes\n#            define acc_pclock_read_getprocesstimes acc_pclock_read_getprocesstimes\n#        endif\nstatic int acc_pclock_read_getprocesstimes(acc_pclock_handle_p h, acc_pclock_p c) {\n\tFILETIME ct, et, kt, ut;\n\tacc_uint64l_t ticks;\n\tif (GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut) == 0)\n\t\treturn -1;\n\tticks = ((acc_uint64l_t) ut.dwHighDateTime << 32) | ut.dwLowDateTime;\n\tif __acc_unlikely\n\t\t(h->ticks_base == 0)\n\t\t\th->ticks_base = ticks;\n\telse\n\t\tticks -= h->ticks_base;\n\tc->tv_sec = (acc_int64l_t) (ticks / 10000000ul);\n\tc->tv_nsec = (acc_uint32l_t) (ticks % 10000000ul) * 100u;\n\tACC_UNUSED(h);\n\treturn 0;\n}\n#    endif\n#    if defined(HAVE_GETRUSAGE) && defined(RUSAGE_SELF)\n#        ifndef acc_pclock_read_getrusage\n#            define acc_pclock_read_getrusage acc_pclock_read_getrusage\n#        endif\nstatic int acc_pclock_read_getrusage(acc_pclock_handle_p h, acc_pclock_p c) {\n\tstruct rusage ru;\n\tif (getrusage(RUSAGE_SELF, &ru) != 0)\n\t\treturn -1;\n#        if defined(acc_int64l_t)\n\tc->tv_sec = ru.ru_utime.tv_sec;\n#        else\n\tc->tv_sec_high = 0;\n\tc->tv_sec_low = ru.ru_utime.tv_sec;\n#        endif\n\tc->tv_nsec = (acc_uint32l_t) (ru.ru_utime.tv_usec * 1000u);\n\tACC_UNUSED(h);\n\treturn 0;\n}\n#    endif\n#    if (__ACCLIB_PCLOCK_USE_PERFCTR)\n#        ifndef acc_pclock_read_perfctr\n#            define acc_pclock_read_perfctr acc_pclock_read_perfctr\n#        endif\nstatic int acc_pclock_read_perfctr(acc_pclock_handle_p h, acc_pclock_p c) {\n\tacc_perfctr_clock_t pcc;\n\tdouble secs;\n\tacc_uint64l_t nsecs;\n\tacc_perfctr_read(&h->pch, &pcc);\n\tif __acc_unlikely\n\t\t(h->ticks_base == 0)\n\t\t\th->ticks_base = pcc.tsc;\n\telse\n\t\tpcc.tsc -= h->ticks_base;\n\tsecs = pcc.tsc * h->pch.tsc_to_seconds;\n\tnsecs = (acc_uint64l_t) (secs * 1000000000.0);\n\tc->tv_sec = nsecs / 1000000000ul;\n\tc->tv_nsec = (acc_uint32l_t) (nsecs % 1000000000ul);\n\tACC_UNUSED(h);\n\treturn 0;\n}\n#    endif\n#    if 0 && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_THREAD_CPUTIME_ID) && defined(acc_int64l_t)\n#        ifndef acc_pclock_read_clock_gettime_t\n#            define acc_pclock_read_clock_gettime_t acc_pclock_read_clock_gettime_t\n#        endif\nstatic int acc_pclock_read_clock_gettime_t(acc_pclock_handle_p h, acc_pclock_p c) {\n\tstruct timespec ts;\n\tif (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0)\n\t\treturn -1;\n\tc->tv_sec = ts.tv_sec;\n\tc->tv_nsec = ts.tv_nsec;\n\tACC_UNUSED(h);\n\treturn 0;\n}\n#    endif\n#    if (ACC_OS_CYGWIN || ACC_OS_WIN32 || ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H) && defined(acc_int64l_t)\n#        ifndef acc_pclock_read_getthreadtimes\n#            define acc_pclock_read_getthreadtimes acc_pclock_read_getthreadtimes\n#        endif\nstatic int acc_pclock_read_getthreadtimes(acc_pclock_handle_p h, acc_pclock_p c) {\n\tFILETIME ct, et, kt, ut;\n\tacc_uint64l_t ticks;\n\tif (GetThreadTimes(GetCurrentThread(), &ct, &et, &kt, &ut) == 0)\n\t\treturn -1;\n\tticks = ((acc_uint64l_t) ut.dwHighDateTime << 32) | ut.dwLowDateTime;\n\tif __acc_unlikely\n\t\t(h->ticks_base == 0)\n\t\t\th->ticks_base = ticks;\n\telse\n\t\tticks -= h->ticks_base;\n\tc->tv_sec = (acc_int64l_t) (ticks / 10000000ul);\n\tc->tv_nsec = (acc_uint32l_t) (ticks % 10000000ul) * 100;\n\tACC_UNUSED(h);\n\treturn 0;\n}\n#    endif\nACCLIB_PUBLIC(int, acc_pclock_open)(acc_pclock_handle_p h, int mode) {\n\tacc_pclock_t c;\n\tint i;\n\th->h = (acclib_handle_t) 0;\n\th->mode = -1;\n\th->name = NULL;\n\th->gettime = 0;\n#    if defined(acc_int64l_t)\n\th->ticks_base = 0;\n#    endif\n\tswitch (mode) {\n\tcase ACC_PCLOCK_REALTIME_HR:\n#    if defined(acc_pclock_read_gettimeofday)\n\t\th->gettime = acc_pclock_read_gettimeofday;\n\t\th->name = \"gettimeofday\";\n#    endif\n\t\tbreak;\n\tcase ACC_PCLOCK_REALTIME:\n#    if defined(acc_pclock_read_gettimeofday)\n\t\th->gettime = acc_pclock_read_gettimeofday;\n\t\th->name = \"gettimeofday\";\n#    endif\n\t\tbreak;\n\tcase ACC_PCLOCK_MONOTONIC_HR:\n#    if defined(acc_pclock_read_uclock)\n\t\th->gettime = acc_pclock_read_uclock;\n\t\th->name = \"uclock\";\n#    endif\n\t\tbreak;\n\tcase ACC_PCLOCK_MONOTONIC:\n#    if defined(acc_pclock_read_clock)\n\t\tif (!h->gettime) {\n\t\t\th->gettime = acc_pclock_read_clock;\n\t\t\th->name = \"clock\";\n\t\t}\n#    endif\n\t\tbreak;\n\tcase ACC_PCLOCK_PROCESS_CPUTIME_ID:\n#    if defined(acc_pclock_read_perfctr)\n\t\tif (acc_perfctr_open(&h->pch) == 0) {\n\t\t\th->gettime = acc_pclock_read_perfctr;\n\t\t\th->name = \"perfctr\";\n\t\t\tbreak;\n\t\t}\n#    endif\n#    if defined(acc_pclock_read_getprocesstimes)\n\t\tif (!h->gettime && acc_pclock_read_getprocesstimes(h, &c) == 0) {\n\t\t\th->gettime = acc_pclock_read_getprocesstimes;\n\t\t\th->name = \"GetProcessTimes\";\n\t\t\tbreak;\n\t\t}\n#    endif\n#    if defined(acc_pclock_read_clock_gettime_p)\n\t\tif (!h->gettime && acc_pclock_read_clock_gettime_p(h, &c) == 0) {\n\t\t\th->gettime = acc_pclock_read_clock_gettime_p;\n\t\t\th->name = \"CLOCK_PROCESS_CPUTIME_ID\";\n\t\t\tbreak;\n\t\t}\n#    endif\n#    if defined(acc_pclock_read_getrusage)\n\t\th->gettime = acc_pclock_read_getrusage;\n\t\th->name = \"getrusage\";\n#    endif\n\t\tbreak;\n\tcase ACC_PCLOCK_THREAD_CPUTIME_ID:\n#    if defined(acc_pclock_read_getthreadtimes)\n\t\tif (!h->gettime && acc_pclock_read_getthreadtimes(h, &c) == 0) {\n\t\t\th->gettime = acc_pclock_read_getthreadtimes;\n\t\t\th->name = \"GetThreadTimes\";\n\t\t}\n#    endif\n#    if defined(acc_pclock_read_clock_gettime_t)\n\t\tif (!h->gettime && acc_pclock_read_clock_gettime_t(h, &c) == 0) {\n\t\t\th->gettime = acc_pclock_read_clock_gettime_t;\n\t\t\th->name = \"CLOCK_THREAD_CPUTIME_ID\";\n\t\t\tbreak;\n\t\t}\n#    endif\n\t\tbreak;\n\t}\n\tif (!h->gettime)\n\t\treturn -1;\n\tif (!h->h)\n\t\th->h = (acclib_handle_t) 1;\n\th->mode = mode;\n\tif (!h->name)\n\t\th->name = \"unknown\";\n\tfor (i = 0; i < 10; i++) {\n\t\tacc_pclock_read(h, &c);\n\t}\n\treturn 0;\n}\n\nACCLIB_PUBLIC(int, acc_pclock_open_default)(acc_pclock_handle_p h) {\n\tif (acc_pclock_open(h, ACC_PCLOCK_PROCESS_CPUTIME_ID) == 0)\n\t\treturn 0;\n\tif (acc_pclock_open(h, ACC_PCLOCK_MONOTONIC_HR) == 0)\n\t\treturn 0;\n\tif (acc_pclock_open(h, ACC_PCLOCK_REALTIME_HR) == 0)\n\t\treturn 0;\n\tif (acc_pclock_open(h, ACC_PCLOCK_MONOTONIC) == 0)\n\t\treturn 0;\n\tif (acc_pclock_open(h, ACC_PCLOCK_REALTIME) == 0)\n\t\treturn 0;\n\tif (acc_pclock_open(h, ACC_PCLOCK_THREAD_CPUTIME_ID) == 0)\n\t\treturn 0;\n\treturn -1;\n}\n\nACCLIB_PUBLIC(int, acc_pclock_close)(acc_pclock_handle_p h) {\n\th->h = (acclib_handle_t) 0;\n\th->mode = -1;\n\th->name = NULL;\n\th->gettime = 0;\n#    if (__ACCLIB_PCLOCK_USE_PERFCTR)\n\tacc_perfctr_close(&h->pch);\n#    endif\n\treturn 0;\n}\n\nACCLIB_PUBLIC(void, acc_pclock_read)(acc_pclock_handle_p h, acc_pclock_p c) {\n\tif (h->gettime) {\n\t\tif (h->gettime(h, c) == 0)\n\t\t\treturn;\n\t}\n#    if defined(acc_int64l_t)\n\tc->tv_sec = 0;\n#    else\n\tc->tv_sec_high = 0;\n\tc->tv_sec_low = 0;\n#    endif\n\tc->tv_nsec = 0;\n}\n\n#    if !defined(ACC_CFG_NO_DOUBLE)\nACCLIB_PUBLIC(double, acc_pclock_get_elapsed)(acc_pclock_handle_p h, const acc_pclock_p start, const acc_pclock_p stop) {\n\tdouble tstop, tstart;\n\tif (!h->h) {\n\t\th->mode = -1;\n\t\treturn 0.0;\n\t}\n#        if defined(acc_int64l_t)\n\ttstop = stop->tv_sec + stop->tv_nsec / 1000000000.0;\n\ttstart = start->tv_sec + start->tv_nsec / 1000000000.0;\n#        else\n\ttstop = stop->tv_sec_low + stop->tv_nsec / 1000000000.0;\n\ttstart = start->tv_sec_low + start->tv_nsec / 1000000000.0;\n#        endif\n\treturn tstop - tstart;\n}\n#    endif\nACCLIB_PUBLIC(int, acc_pclock_flush_cpu_cache)(acc_pclock_handle_p h, unsigned flags) {\n\tif (h->h) {\n#    if (__ACCLIB_PCLOCK_USE_PERFCTR)\n\t\treturn acc_perfctr_flush_cpu_cache(&h->pch, flags);\n#    endif\n\t}\n\tACC_UNUSED(h);\n\tACC_UNUSED(flags);\n\treturn -1;\n}\n\n#    if defined(__ACCLIB_PCLOCK_NEED_WARN_POP)\n#        if (ACC_CC_MSC && (_MSC_VER >= 1200))\n#            pragma warning(pop)\n#        else\n#            error \"__ACCLIB_PCLOCK_NEED_WARN_POP\"\n#        endif\n#        undef __ACCLIB_PCLOCK_NEED_WARN_POP\n#    endif\n#endif\n#if defined(ACC_WANT_ACCLIB_UCLOCK)\n#    undef ACC_WANT_ACCLIB_UCLOCK\n#    define __ACCLIB_UCLOCK_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\n#    if (ACC_OS_DOS16 || ACC_OS_WIN16)\n#    elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n#    elif (ACC_OS_CYGWIN || ACC_OS_WIN32 || ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H)\n#        if ((ACC_CC_DMC && (__DMC__ < 0x838)) || ACC_CC_LCCWIN32)\n#            define __ACCLIB_UCLOCK_USE_CLOCK 1\n#        else\n#            define __ACCLIB_UCLOCK_USE_WINMM 1\n#            if (ACC_CC_MSC && (_MSC_VER >= 1200))\n#                pragma warning(push)\n#                define __ACCLIB_UCLOCK_NEED_WARN_POP 1\n#            endif\n#            if (ACC_CC_MSC && (_MSC_VER >= 900))\n#                pragma warning(disable: 4201)\n#            elif (ACC_CC_MWERKS)\n#                define LPUINT __ACC_MMSYSTEM_H_LPUINT\n#            endif\n#            if 1\n#                include <mmsystem.h>\n#            else\n#                if (ACC_CC_INTELC || ACC_CC_MSC || ACC_CC_PELLESC)\nACC_EXTERN_C __declspec(dllimport)\nunsigned long __stdcall timeGetTime(void);\n#                else\nACC_EXTERN_C unsigned long __stdcall timeGetTime(void);\n#                endif\n#            endif\n#            if (ACC_CC_DMC)\n#                pragma DMC includelib \"winmm.lib\"\n#            elif (ACC_CC_INTELC || ACC_CC_MSC || ACC_CC_PELLESC)\n#                pragma comment(lib, \"winmm.lib\")\n#            elif (ACC_CC_MWERKS && (__MWERKS__ >= 0x3000))\n#                pragma comment(lib, \"winmm.lib\")\n#            elif (ACC_CC_SYMANTECC)\n#                pragma SC includelib \"winmm.lib\"\n#            elif (ACC_CC_WATCOMC && (__WATCOMC__ >= 1050))\n#                pragma library(\"winmm.lib\")\n#            endif\n#        endif\n#    elif (ACC_OS_CYGWIN || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_TOS || ACC_OS_WIN32 || ACC_OS_WIN64)\n#        define __ACCLIB_UCLOCK_USE_CLOCK 1\n#    elif (ACC_OS_CONSOLE) && defined(CLOCKS_PER_SEC)\n#        define __ACCLIB_UCLOCK_USE_CLOCK 1\n#    elif (ACC_LIBC_ISOC90 || ACC_LIBC_ISOC99) && defined(CLOCKS_PER_SEC)\n#        define __ACCLIB_UCLOCK_USE_CLOCK 1\n#    endif\n#    if (__ACCLIB_UCLOCK_USE_CLOCK) && !defined(CLOCKS_PER_SEC)\n#        if defined(CLK_TCK)\n#            define CLOCKS_PER_SEC CLK_TCK\n#        else\n#            undef __ACCLIB_UCLOCK_USE_CLOCK\n#        endif\n#    endif\n#    if (__ACCLIB_UCLOCK_USE_GETRUSAGE)\n#        if !defined(RUSAGE_SELF)\n#            undef __ACCLIB_UCLOCK_USE_GETRUSAGE\n#        endif\n#    endif\nACCLIB_PUBLIC(int, acc_uclock_open)(acc_uclock_handle_p h) {\n\tint i;\n#    if (__ACCLIB_UCLOCK_USE_QPC)\n\tLARGE_INTEGER li;\n#    endif\n\th->h = (acclib_handle_t) 1;\n\th->mode = 0;\n\th->name = NULL;\n#    if (__ACCLIB_UCLOCK_USE_PERFCTR)\n\th->pch.h = 0;\n\tif (h->mode == 0 && acc_perfctr_open(&h->pch) == 0)\n\t\th->mode = 2;\n#    endif\n#    if (__ACCLIB_UCLOCK_USE_QPC)\n\th->qpf = 0.0;\n\tif (h->mode == 0 && QueryPerformanceFrequency(&li) != 0) {\n\t\tdouble d = (double)li.QuadPart;\n\t\tif (d > 0.0 && QueryPerformanceCounter(&li) != 0) {\n\t\t\th->mode = 3;\n\t\t\th->qpf = d;\n\t\t}\n\t}\n#    endif\n\tfor (i = 0; i < 10; i++) {\n\t\tacc_uclock_t c;\n\t\tacc_uclock_read(h, &c);\n\t}\n\treturn 0;\n}\n\nACCLIB_PUBLIC(int, acc_uclock_close)(acc_uclock_handle_p h) {\n\th->h = (acclib_handle_t) 0;\n\th->mode = -1;\n\th->name = NULL;\n#    if (__ACCLIB_UCLOCK_USE_PERFCTR)\n\tacc_perfctr_close(&h->pch);\n#    endif\n\treturn 0;\n}\n\nACCLIB_PUBLIC(void, acc_uclock_read)(acc_uclock_handle_p h, acc_uclock_p c) {\n#    if (__ACCLIB_UCLOCK_USE_RDTSC)\n\tacc_tsc_read((acc_uint32e_t *) (void *)&c->tsc);\n#    endif\n#    if (__ACCLIB_UCLOCK_USE_PERFCTR)\n\tif (h->pch.h) {\n\t\tacc_perfctr_read(&h->pch, &c->pcc);\n\t\tif (h->mode > 0 && h->mode <= 2)\n\t\t\treturn;\n\t}\n#    endif\n#    if (__ACCLIB_UCLOCK_USE_QPC)\n\tif (h->qpf > 0.0) {\n\t\tLARGE_INTEGER li;\n\t\tif (QueryPerformanceCounter(&li) != 0) {\n\t\t\tc->qpc = (acc_int64l_t) li.QuadPart;\n\t\t\tif (h->mode > 0 && h->mode <= 3)\n\t\t\t\treturn;\n\t\t} else {\n\t\t\th->mode = 0;\n\t\t\th->qpf = 0.0;\n\t\t\tc->qpc = 0;\n\t\t}\n\t}\n#    endif\n\t{\n#    if (ACC_OS_DOS16 || ACC_OS_WIN16)\n#        if (ACC_CC_AZTECC)\n\t\tc->ticks.t32 = 0;\n#        else\n\t\tunion REGS ri, ro;\n\t\tri.x.ax = 0x2c00;\n\t\tint86(0x21, &ri, &ro);\n\t\tc->ticks.t32 = ro.h.ch * 60UL * 60UL * 100UL + ro.h.cl * 60UL * 100UL + ro.h.dh * 100UL + ro.h.dl;\n#        endif\n#    elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n\t\tc->ticks.t64 = uclock();\n#    elif (__ACCLIB_UCLOCK_USE_CLOCK) && defined(acc_int64l_t)\n\t\tc->ticks.t64 = clock();\n#    elif (__ACCLIB_UCLOCK_USE_CLOCK)\n\t\tc->ticks.t32 = clock();\n#    elif (__ACCLIB_UCLOCK_USE_WINMM)\n\t\tc->ticks.t32 = timeGetTime();\n#    elif (__ACCLIB_UCLOCK_USE_GETRUSAGE)\n\t\tstruct rusage ru;\n\t\tif (getrusage(RUSAGE_SELF, &ru) != 0)\n\t\t\tc->ticks.td = 0;\n\t\telse\n\t\t\tc->ticks.td = ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1000000.0;\n#    elif (HAVE_GETTIMEOFDAY)\n\t\tstruct timeval tv;\n\t\tif (gettimeofday(&tv, 0) != 0)\n\t\t\tc->ticks.td = 0;\n\t\telse\n\t\t\tc->ticks.td = tv.tv_sec + tv.tv_usec / 1000000.0;\n#    else\n\t\tACC_UNUSED(c);\n#    endif\n\t}\n\tACC_UNUSED(h);\n}\n\nACCLIB_PUBLIC(double, acc_uclock_get_elapsed) (acc_uclock_handle_p h, const acc_uclock_p start, const acc_uclock_p stop) {\n\tdouble d;\n\tif (!h->h) {\n\t\th->mode = -1;\n\t\treturn 0.0;\n\t}\n#    if (__ACCLIB_UCLOCK_USE_RDTSC)\n\tif (h->mode == 1) {\n\t\tif (!h->name)\n\t\t\th->name = \"rdtsc\";\n\t\td = (double)((acc_int64l_t) stop->tsc - (acc_int64l_t) start->tsc);\n\t\treturn d / 1000000000.0;\n\t}\n#    endif\n#    if (__ACCLIB_UCLOCK_USE_PERFCTR)\n\tif (h->pch.h && h->mode == 2) {\n\t\tif (!h->name)\n\t\t\th->name = \"perfctr\";\n\t\treturn acc_perfctr_get_elapsed(&h->pch, &start->pcc, &stop->pcc);\n\t}\n#    endif\n#    if (__ACCLIB_UCLOCK_USE_QPC)\n\tif (h->qpf > 0.0 && h->mode == 3) {\n\t\tif (!h->name)\n\t\t\th->name = \"qpc\";\n\t\tif (start->qpc == 0 || stop->qpc == 0)\n\t\t\treturn 0.0;\n\t\treturn (double)(stop->qpc - start->qpc) / h->qpf;\n\t}\n#    endif\n#    if (ACC_OS_DOS16 || ACC_OS_WIN16)\n\th->mode = 11;\n\tif (!h->name)\n\t\th->name = \"uclock\";\n\td = (double)(stop->ticks.t32 - start->ticks.t32) / 100.0;\n\tif (d < 0.0)\n\t\td += 86400.0;\n#    elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n\th->mode = 12;\n\tif (!h->name)\n\t\th->name = \"uclock\";\n\td = (double)(stop->ticks.t64 - start->ticks.t64) / (UCLOCKS_PER_SEC);\n#    elif (__ACCLIB_UCLOCK_USE_CLOCK) && defined(acc_int64l_t)\n\th->mode = 13;\n\tif (!h->name)\n\t\th->name = \"clock\";\n\t{\n\t\tacc_int64l_t t;\n\t\tt = stop->ticks.t64 - start->ticks.t64;\n\t\tif (t < 0)\n\t\t\tt += sizeof(clock_t) == 4 ? ACC_INT64_C(0x100000000) : ACC_INT64_C(0);\n\t\td = (double)t / (CLOCKS_PER_SEC);\n\t}\n#    elif (__ACCLIB_UCLOCK_USE_CLOCK)\n\th->mode = 14;\n\tif (!h->name)\n\t\th->name = \"clock\";\n\td = (double)(stop->ticks.t32 - start->ticks.t32) / (CLOCKS_PER_SEC);\n#    elif (__ACCLIB_UCLOCK_USE_WINMM)\n\th->mode = 15;\n\tif (!h->name)\n\t\th->name = \"timeGetTime\";\n\td = (double)(stop->ticks.t32 - start->ticks.t32) / 1000.0;\n#    elif (__ACCLIB_UCLOCK_USE_GETRUSAGE)\n\th->mode = 16;\n\tif (!h->name)\n\t\th->name = \"getrusage\";\n\td = stop->ticks.td - start->ticks.td;\n#    elif (HAVE_GETTIMEOFDAY)\n\th->mode = 17;\n\tif (!h->name)\n\t\th->name = \"gettimeofday\";\n\td = stop->ticks.td - start->ticks.td;\n#    else\n\th->mode = 0;\n\td = 0.0;\n#    endif\n\treturn d;\n}\n\nACCLIB_PUBLIC(int, acc_uclock_flush_cpu_cache)(acc_uclock_handle_p h, unsigned flags) {\n\tif (h->h) {\n#    if (__ACCLIB_UCLOCK_USE_PERFCTR)\n\t\treturn acc_perfctr_flush_cpu_cache(&h->pch, flags);\n#    endif\n\t}\n\tACC_UNUSED(h);\n\tACC_UNUSED(flags);\n\treturn -1;\n}\n\n#    if defined(__ACCLIB_UCLOCK_NEED_WARN_POP)\n#        if (ACC_CC_MSC && (_MSC_VER >= 1200))\n#            pragma warning(pop)\n#        else\n#            error \"__ACCLIB_UCLOCK_NEED_WARN_POP\"\n#        endif\n#        undef __ACCLIB_UCLOCK_NEED_WARN_POP\n#    endif\n#endif\n#if defined(ACC_WANT_ACCLIB_MISC)\n#    undef ACC_WANT_ACCLIB_MISC\n#    define __ACCLIB_MISC_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)                r __ACCLIB_FUNCNAME(f)\n#    endif\n#    if !defined(ACCLIB_PUBLIC_NOINLINE)\n#        if !defined(__acc_noinline)\n#            define ACCLIB_PUBLIC_NOINLINE(r,f)     r __ACCLIB_FUNCNAME(f)\n#        elif (ACC_CC_GNUC >= 0x030400ul) || (ACC_CC_LLVM)\n#            define ACCLIB_PUBLIC_NOINLINE(r,f)     __acc_noinline __attribute__((__used__)) r __ACCLIB_FUNCNAME(f)\n#        else\n#            define ACCLIB_PUBLIC_NOINLINE(r,f)     __acc_noinline r __ACCLIB_FUNCNAME(f)\n#        endif\n#    endif\n#    if (ACC_OS_WIN32 && ACC_CC_PELLESC && (__POCC__ >= 290))\n#        pragma warn(push)\n#        pragma warn(disable:2007)\n#    endif\nACCLIB_PUBLIC(const char *, acc_getenv)(const char *s) {\n#    if defined(HAVE_GETENV)\n\treturn getenv(s);\n#    else\n\tACC_UNUSED(s);\n\treturn (const char *)0;\n#    endif\n}\n\nACCLIB_PUBLIC(acclib_handle_t, acc_get_osfhandle) (int fd) {\n\tif (fd < 0)\n\t\treturn -1;\n#    if (ACC_OS_CYGWIN)\n\treturn get_osfhandle(fd);\n#    elif (ACC_OS_EMX && defined(__RSXNT__))\n\treturn -1;\n#    elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)\n\treturn -1;\n#    elif (ACC_OS_WIN32 || ACC_OS_WIN64)\n#        if (ACC_CC_PELLESC && (__POCC__ < 280))\n\treturn -1;\n#        elif (ACC_CC_WATCOMC && (__WATCOMC__ < 1000))\n\treturn -1;\n#        elif (ACC_CC_WATCOMC && (__WATCOMC__ < 1100))\n\treturn _os_handle(fd);\n#        else\n\treturn _get_osfhandle(fd);\n#        endif\n#    else\n\treturn fd;\n#    endif\n}\n\nACCLIB_PUBLIC(int, acc_set_binmode)(int fd, int binary) {\n#    if (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)\n\tFILE *fp;\n\tint old_binary;\n\tif (fd == STDIN_FILENO)\n\t\tfp = stdin;\n\telse if (fd == STDOUT_FILENO)\n\t\tfp = stdout;\n\telse if (fd == STDERR_FILENO)\n\t\tfp = stderr;\n\telse\n\t\treturn -1;\n\told_binary = fp->__mode.__binary;\n\t__set_binmode(fp, binary ? 1 : 0);\n\treturn old_binary ? 1 : 0;\n#    elif (ACC_ARCH_M68K && ACC_OS_TOS)\n\tACC_UNUSED(fd);\n\tACC_UNUSED(binary);\n\treturn -1;\n#    elif (ACC_OS_DOS16 && (ACC_CC_AZTECC || ACC_CC_PACIFICC))\n\tACC_UNUSED(fd);\n\tACC_UNUSED(binary);\n\treturn -1;\n#    elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n\tint r;\n\tunsigned old_flags = __djgpp_hwint_flags;\n\tACC_COMPILE_TIME_ASSERT(O_BINARY > 0)\n\t\tACC_COMPILE_TIME_ASSERT(O_TEXT > 0)\n\t\tif (fd < 0)\n\t\treturn -1;\n\tr = setmode(fd, binary ? O_BINARY : O_TEXT);\n\tif ((old_flags & 1u) != (__djgpp_hwint_flags & 1u))\n\t\t__djgpp_set_ctrl_c(!(old_flags & 1));\n\tif (r == -1)\n\t\treturn -1;\n\treturn (r & O_TEXT) ? 0 : 1;\n#    elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)\n\tif (fd < 0)\n\t\treturn -1;\n\tACC_UNUSED(binary);\n\treturn 1;\n#    elif (ACC_OS_DOS32 && ACC_CC_HIGHC)\n\tFILE *fp;\n\tint r;\n\tif (fd == fileno(stdin))\n\t\tfp = stdin;\n\telse if (fd == fileno(stdout))\n\t\tfp = stdout;\n\telse if (fd == fileno(stderr))\n\t\tfp = stderr;\n\telse\n\t\treturn -1;\n\tr = _setmode(fp, binary ? _BINARY : _TEXT);\n\tif (r == -1)\n\t\treturn -1;\n\treturn (r & _BINARY) ? 1 : 0;\n#    elif (ACC_OS_WIN32 && ACC_CC_MWERKS) && defined(__MSL__)\n\tACC_UNUSED(fd);\n\tACC_UNUSED(binary);\n\treturn -1;\n#    elif (ACC_OS_CYGWIN && (ACC_CC_GNUC < 0x025a00ul))\n\tACC_UNUSED(fd);\n\tACC_UNUSED(binary);\n\treturn -1;\n#    elif (ACC_OS_CYGWIN || ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)\n\tint r;\n#        if !defined(ACC_CC_ZORTECHC)\n\tACC_COMPILE_TIME_ASSERT(O_BINARY > 0)\n#        endif\n\t\tACC_COMPILE_TIME_ASSERT(O_TEXT > 0)\n\t\tif (fd < 0)\n\t\treturn -1;\n\tr = setmode(fd, binary ? O_BINARY : O_TEXT);\n\tif (r == -1)\n\t\treturn -1;\n\treturn (r & O_TEXT) ? 0 : 1;\n#    else\n\tif (fd < 0)\n\t\treturn -1;\n\tACC_UNUSED(binary);\n\treturn 1;\n#    endif\n}\n\nACCLIB_PUBLIC(int, acc_isatty)(int fd) {\n\tif (fd < 0)\n\t\treturn 0;\n#    if (ACC_OS_DOS16 && !defined(ACC_CC_AZTECC))\n\t{\n\t\tunion REGS ri, ro;\n\t\tri.x.ax = 0x4400;\n\t\tri.x.bx = fd;\n\t\tint86(0x21, &ri, &ro);\n\t\tif ((ro.x.cflag & 1) == 0)\n\t\t\tif ((ro.x.ax & 0x83) != 0x83)\n\t\t\t\treturn 0;\n\t}\n#    elif (ACC_OS_DOS32 && ACC_CC_WATCOMC)\n\t{\n\t\tunion REGS ri, ro;\n\t\tri.w.ax = 0x4400;\n\t\tri.w.bx = (unsigned short)fd;\n\t\tint386(0x21, &ri, &ro);\n\t\tif ((ro.w.cflag & 1) == 0)\n\t\t\tif ((ro.w.ax & 0x83) != 0x83)\n\t\t\t\treturn 0;\n\t}\n#    elif (ACC_HAVE_WINDOWS_H)\n\t{\n\t\tacclib_handle_t h = __ACCLIB_FUNCNAME(acc_get_osfhandle) (fd);\n\t\tif ((HANDLE) h != INVALID_HANDLE_VALUE) {\n\t\t\tDWORD d = 0;\n\t\t\tif (GetConsoleMode((HANDLE) h, &d) == 0)\n\t\t\t\treturn 0;\n\t\t}\n\t}\n#    endif\n#    if defined(HAVE_ISATTY)\n\treturn (isatty(fd)) ? 1 : 0;\n#    else\n\treturn 0;\n#    endif\n}\n\nACCLIB_PUBLIC(int, acc_mkdir)(const char *name, unsigned mode) {\n#    if !defined(HAVE_MKDIR)\n\tACC_UNUSED(name);\n\tACC_UNUSED(mode);\n\treturn -1;\n#    elif (ACC_ARCH_M68K && ACC_OS_TOS && (ACC_CC_PUREC || ACC_CC_TURBOC))\n\tACC_UNUSED(mode);\n\treturn Dcreate(name);\n#    elif (ACC_OS_DOS32 && ACC_CC_GNUC) && defined(__DJGPP__)\n\treturn mkdir(name, mode);\n#    elif (ACC_OS_WIN32 && ACC_CC_GNUC) && defined(__PW32__)\n\treturn mkdir(name, mode);\n#    elif (ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)\n\tACC_UNUSED(mode);\n#        if (ACC_CC_HIGHC || ACC_CC_PACIFICC)\n\treturn mkdir((char *)name);\n#        else\n\treturn mkdir(name);\n#        endif\n#    else\n\treturn mkdir(name, mode);\n#    endif\n}\n\nACCLIB_PUBLIC(int, acc_rmdir)(const char *name) {\n#    if !defined(HAVE_RMDIR)\n\tACC_UNUSED(name);\n\treturn -1;\n#    elif ((ACC_OS_DOS16 || ACC_OS_DOS32) && (ACC_CC_HIGHC || ACC_CC_PACIFICC))\n\treturn rmdir((char *)name);\n#    else\n\treturn rmdir(name);\n#    endif\n}\n\n#    if defined(acc_int32e_t)\nACCLIB_PUBLIC(acc_int32e_t, acc_muldiv32s) (acc_int32e_t a, acc_int32e_t b, acc_int32e_t x) {\n\tacc_int32e_t r = 0;\n\tif __acc_likely\n\t\t(x != 0) {\n#        if defined(acc_int64l_t)\n\t\tr = (acc_int32e_t) (((acc_int64l_t) a * b) / x);\n#        else\n\t\tACC_UNUSED(a);\n\t\tACC_UNUSED(b);\n#        endif\n\t\t}\n\treturn r;\n}\n\nACCLIB_PUBLIC(acc_uint32e_t, acc_muldiv32u) (acc_uint32e_t a, acc_uint32e_t b, acc_uint32e_t x) {\n\tacc_uint32e_t r = 0;\n\tif __acc_likely\n\t\t(x != 0) {\n#        if defined(acc_int64l_t)\n\t\tr = (acc_uint32e_t) (((acc_uint64l_t) a * b) / x);\n#        else\n\t\tACC_UNUSED(a);\n\t\tACC_UNUSED(b);\n#        endif\n\t\t}\n\treturn r;\n}\n#    endif\n#    if 0\nACCLIB_PUBLIC_NOINLINE(int, acc_syscall_clock_gettime)(int c) {\n}\n#    endif\n#    if (ACC_OS_WIN16)\nACC_EXTERN_C void __far __pascal DebugBreak(void);\n#    endif\nACCLIB_PUBLIC_NOINLINE(void, acc_debug_break) (void) {\n#    if (ACC_OS_WIN16)\n\tDebugBreak();\n#    elif (ACC_ARCH_I086)\n#    elif (ACC_OS_WIN64) && (ACC_HAVE_WINDOWS_H)\n\tDebugBreak();\n#    elif defined(ACC_CFG_NO_INLINE_ASM) && (ACC_OS_WIN32) && (ACC_HAVE_WINDOWS_H)\n\tDebugBreak();\n#    elif (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)\n\t__asm__ __volatile__(\"int $3\\n\":::__ACC_ASM_CLOBBER);\n#    elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_MSC)\n\t__asm {\n\tint 3}\n#    elif (ACC_OS_WIN32) && (ACC_HAVE_WINDOWS_H)\n\tDebugBreak();\n#    else\n\t*(volatile int *)0x1 = -1;\n#    endif\n}\n\nACCLIB_PUBLIC_NOINLINE(void, acc_debug_nop) (void) {\n}\n\nACCLIB_PUBLIC_NOINLINE(int, acc_debug_align_check_query) (void) {\n#    if (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)\n\tsize_t r;\n\t__asm__ __volatile__(\"pushf\\n pop %0\\n\":\"=a\"(r)::__ACC_ASM_CLOBBER);\n\treturn (int)(r >> 18) & 1;\n#    elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_MSC)\n\tunsigned long r;\n\t__asm {\n\tpushf pop eax mov r, eax}\n\treturn (int)(r >> 18) & 1;\n#    else\n\treturn -1;\n#    endif\n}\n\nACCLIB_PUBLIC_NOINLINE(int, acc_debug_align_check_enable)(int v) {\n\tint r;\n#    if (ACC_ARCH_AMD64) && (ACC_ASM_SYNTAX_GNUC)\n\tif (v) {\n\t\t__asm__ __volatile__(\"pushf\\n orl $262144,(%%rsp)\\n popf\\n\":::__ACC_ASM_CLOBBER);\n\t} else {\n\t\t__asm__ __volatile__(\"pushf\\n andl $-262145,(%%rsp)\\n popf\\n\":::__ACC_ASM_CLOBBER);\n\t}\n\tr = 0;\n#    elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)\n\tif (v) {\n\t\t__asm__ __volatile__(\"pushf\\n orl $262144,(%%esp)\\n popf\\n\":::__ACC_ASM_CLOBBER);\n\t} else {\n\t\t__asm__ __volatile__(\"pushf\\n andl $-262145,(%%esp)\\n popf\\n\":::__ACC_ASM_CLOBBER);\n\t}\n\tr = 0;\n#    elif (ACC_ARCH_I386) && (ACC_ASM_SYNTAX_MSC)\n\tif (v) {\n\t\t__asm {\n\t\tpushf or dword ptr[esp], 262144 popf}\n\t} else {\n\t\t__asm {\n\t\tpushf and dword ptr[esp], -262145 popf}\n\t}\n\tr = 0;\n#    else\n\tr = -1;\n#    endif\n\tACC_UNUSED(v);\n\treturn r;\n}\n\nACCLIB_PUBLIC_NOINLINE(unsigned, acc_debug_running_on_qemu)(void) {\n\tunsigned r = 0;\n#    if (ACC_OS_POSIX_LINUX || ACC_OS_WIN32 || ACC_OS_WIN64)\n\tconst char *p;\n\tp = acc_getenv(\"ACC_ENV_RUNNING_ON_QEMU\");\n\tif (p) {\n\t\tif (p[0] == 0)\n\t\t\tr = 0;\n\t\telse if ((p[0] >= '0' && p[0] <= '9') && p[1] == 0)\n\t\t\tr = p[0] - '0';\n\t\telse\n\t\t\tr = 1;\n\t}\n#    endif\n\treturn r;\n}\n\nACCLIB_PUBLIC_NOINLINE(unsigned, acc_debug_running_on_valgrind)(void) {\n#    if (ACC_ARCH_AMD64 || ACC_ARCH_I386) && (ACC_ASM_SYNTAX_GNUC)\n\tvolatile unsigned long args[5] = { 0x1001, 0, 0, 0, 0 };\n\tunsigned long r = 0;\n\t__asm__ __volatile__(\".byte 0xc1,0xc0,0x1d,0xc1,0xc0,0x03,0xc1,0xc8,0x1b,0xc1,0xc8,0x05,0xc1,0xc0,0x0d,0xc1,0xc0,0x13\\n\":\"=d\"(r):\"a\"(&args[0]), \"d\"(r):__ACC_ASM_CLOBBER);\n\treturn (unsigned)r;\n#    else\n\treturn 0;\n#    endif\n}\n\n#    if (ACC_OS_WIN32 && ACC_CC_PELLESC && (__POCC__ >= 290))\n#        pragma warn(pop)\n#    endif\n#endif\n#if defined(ACC_WANT_ACCLIB_WILDARGV)\n#    undef ACC_WANT_ACCLIB_WILDARGV\n#    define __ACCLIB_WILDARGV_CH_INCLUDED 1\n#    if !defined(ACCLIB_PUBLIC)\n#        define ACCLIB_PUBLIC(r,f)    r __ACCLIB_FUNCNAME(f)\n#    endif\n#    if (ACC_OS_DOS16 || ACC_OS216 || ACC_OS_WIN16)\n#        if 0 && (ACC_CC_MSC)\nACC_EXTERN_C int __acc_cdecl __setargv(void);\nACC_EXTERN_C int __acc_cdecl _setargv(void);\nACC_EXTERN_C int __acc_cdecl _setargv(void) {\n\treturn __setargv();\n}\n#        endif\n#    endif\n#    if (ACC_OS_WIN32 || ACC_OS_WIN64)\n#        if (ACC_CC_INTELC || ACC_CC_MSC)\nACC_EXTERN_C int __acc_cdecl __setargv(void);\nACC_EXTERN_C int __acc_cdecl _setargv(void);\nACC_EXTERN_C int __acc_cdecl _setargv(void) {\n\treturn __setargv();\n}\n#        endif\n#    endif\n#    if (ACC_OS_EMX)\n#        define __ACCLIB_HAVE_ACC_WILDARGV 1\nACCLIB_PUBLIC(void, acc_wildargv)(int *argc, char ***argv) {\n\tif (argc && argv) {\n\t\t_response(argc, argv);\n\t\t_wildcard(argc, argv);\n\t}\n}\n#    endif\n#    if (ACC_OS_CONSOLE_PSP) && defined(__PSPSDK_DEBUG__)\n#        define __ACCLIB_HAVE_ACC_WILDARGV 1\nACC_EXTERN_C int acc_psp_init_module(int *, char ***, int);\nACCLIB_PUBLIC(void, acc_wildargv) (int *argc, char ***argv) {\n\tacc_psp_init_module(argc, argv, -1);\n}\n#    endif\n#    if !defined(__ACCLIB_HAVE_ACC_WILDARGV)\n#        define __ACCLIB_HAVE_ACC_WILDARGV 1\nACCLIB_PUBLIC(void, acc_wildargv) (int *argc, char ***argv) {\n#        if 1 && (ACC_ARCH_I086PM)\n\tif (ACC_MM_AHSHIFT != 3) {\n\t\texit(1);\n\t}\n#        elif 1 && (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)\n\t__binmode(1);\n\tif (isatty(1))\n\t\t__set_binmode(stdout, 0);\n\tif (isatty(2))\n\t\t__set_binmode(stderr, 0);\n#        endif\n\tACC_UNUSED(argc);\n\tACC_UNUSED(argv);\n}\n#    endif\n#endif\n\n/* vim:set ts=4 et: */\n"
  },
  {
    "path": "include/lzo/portab.h",
    "content": "/* portab.h -- portability layer\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n   All Rights Reserved.\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU General Public License as\n   published by the Free Software Foundation; either version 2 of\n   the License, or (at your option) any later version.\n\n   The LZO library 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   You should have received a copy of the GNU General Public License\n   along with the LZO library; see the file COPYING.\n   If not, write to the Free Software Foundation, Inc.,\n   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\n   Markus F.X.J. Oberhumer\n   <markus@oberhumer.com>\n   http://www.oberhumer.com/opensource/lzo/\n */\n\n#include \"lzo/lzoconf.h\"\n\n#if (LZO_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1200))\n   /* avoid `-W4' warnings in system header files */\n#    pragma warning(disable: 4201 4214 4514)\n#endif\n#if (LZO_CC_MSC && (_MSC_VER >= 1300))\n   /* avoid `-Wall' warnings in system header files */\n#    pragma warning(disable: 4163 4255 4820)\n   /* avoid warnings about inlining */\n#    pragma warning(disable: 4710 4711)\n#endif\n#if (LZO_CC_MSC && (_MSC_VER >= 1400))\n   /* avoid warnings when using \"deprecated\" POSIX functions */\n#    pragma warning(disable: 4996)\n#endif\n#if (LZO_CC_PELLESC && (__POCC__ >= 290))\n#    pragma warn(disable:2002)\n#endif\n\n/*************************************************************************\n//\n**************************************************************************/\n\n#if defined(__LZO_MMODEL_HUGE) || !(defined(LZO_LIBC_ISOC90) || defined(LZO_LIBC_ISOC99))\n\n#    include \"portab_a.h\"\n\n#else\n\n/* INFO:\n *   The \"portab_a.h\" version above uses the ACC library to add\n *   support for ancient systems (like 16-bit DOS) and to provide\n *   some gimmicks like Windows high-resolution timers.\n *   Still, on any halfway modern machine you can also use the\n *   following pure ANSI-C code instead.\n */\n\n#    include <stddef.h>\n#    include <stdlib.h>\n#    include <stdio.h>\n#    include <string.h>\n#    include <ctype.h>\n#    include <time.h>\n#    if defined(CLK_TCK) && !defined(CLOCKS_PER_SEC)\n#        define CLOCKS_PER_SEC CLK_TCK\n#    endif\n\n#    if defined(WANT_LZO_MALLOC)\n#        define lzo_malloc(a)         (malloc(a))\n#        define lzo_free(a)           (free(a))\n#    endif\n#    if defined(WANT_LZO_FREAD)\n#        define lzo_fread(f,b,s)      (fread(b,1,s,f))\n#        define lzo_fwrite(f,b,s)     (fwrite(b,1,s,f))\n#    endif\n#    if defined(WANT_LZO_UCLOCK)\n#        define lzo_uclock_handle_t   int\n#        define lzo_uclock_t          double\n#        define lzo_uclock_open(a)    ((void)(a))\n#        define lzo_uclock_close(a)   ((void)(a))\n#        define lzo_uclock_read(a,b)  *(b) = (clock() / (double)(CLOCKS_PER_SEC))\n#        define lzo_uclock_get_elapsed(a,b,c) (*(c) - *(b))\n#    endif\n#    if defined(WANT_LZO_WILDARGV)\n#        define lzo_wildargv(a,b)     ((void)0)\n#    endif\n\n#endif\n\n/*************************************************************************\n// misc\n**************************************************************************/\n\n/* turn on assertions */\n#undef NDEBUG\n#include <assert.h>\n\n/* just in case */\n#undef xmalloc\n#undef xfree\n#undef xread\n#undef xwrite\n#undef xputc\n#undef xgetc\n#undef xread32\n#undef xwrite32\n\n#if defined(WANT_LZO_UCLOCK)\n\n/* High quality benchmarking.\n *\n * Flush the CPU cache to get more accurate benchmark values.\n * This needs custom kernel patches. As a result - in combination with\n * the perfctr Linux kernel patches - accurate high-quality benchmarking\n * is possible.\n *\n * All other methods (rdtsc, QueryPerformanceCounter, gettimeofday, ...)\n * are completely unreliable for our purposes, and the only other\n * option is to boot into a legacy single-task operating system\n * like plain MSDOS and to directly reprogram the hardware clock.\n * [The djgpp2 port of the gcc compiler has support functions for this.]\n *\n * Also, for embedded systems it's best to benchmark by using a\n * CPU emulator/simulator software that can exactly count all\n * virtual clock ticks.\n */\n\n#    if !defined(lzo_uclock_flush_cpu_cache)\n#        define lzo_uclock_flush_cpu_cache(h,flags)  ((void)(h))\n#    endif\n\n#endif\n\n/*\nvi:ts=4:et\n*/\n"
  },
  {
    "path": "include/lzo/portab_a.h",
    "content": "/* portab_a.h -- advanced portability layer\n\n   This file is part of the LZO real-time data compression library.\n\n   Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer\n   Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer\n   All Rights Reserved.\n\n   The LZO library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU General Public License as\n   published by the Free Software Foundation; either version 2 of\n   the License, or (at your option) any later version.\n\n   The LZO library 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   You should have received a copy of the GNU General Public License\n   along with the LZO library; see the file COPYING.\n   If not, write to the Free Software Foundation, Inc.,\n   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\n   Markus F.X.J. Oberhumer\n   <markus@oberhumer.com>\n   http://www.oberhumer.com/opensource/lzo/\n */\n\n/*************************************************************************\n// use the ACC library for the hard work\n**************************************************************************/\n\n#if defined(LZO_HAVE_CONFIG_H)\n#    define ACC_CONFIG_NO_HEADER 1\n#endif\n\n#define ACC_WANT_ACC_INCD_H 1\n#define ACC_WANT_ACC_INCE_H 1\n#if defined(__LZO_MMODEL_HUGE) || defined(WANT_LZO_UCLOCK) || defined(WANT_LZO_WILDARGV)\n#    define ACC_WANT_ACC_INCI_H 1\n#    define ACC_WANT_ACC_LIB_H 1\n#endif\n#include \"miniacc.h\"\n\n#if defined(WANT_LZO_MALLOC)\n#    if defined(__LZO_MMODEL_HUGE)\n#        define ACC_WANT_ACCLIB_HALLOC 1\n#    else\n#        define acc_halloc(a)           (malloc(a))\n#        define acc_hfree(a)            (free(a))\n#    endif\n#endif\n#if defined(WANT_LZO_FREAD)\n#    if defined(__LZO_MMODEL_HUGE)\n#        define ACC_WANT_ACCLIB_HFREAD 1\n#    else\n#        define acc_hfread(f,b,s)       (fread(b,1,s,f))\n#        define acc_hfwrite(f,b,s)      (fwrite(b,1,s,f))\n#    endif\n#endif\n#if defined(WANT_LZO_UCLOCK)\n#    define ACC_WANT_ACCLIB_PCLOCK 1\n#    if 0 && (LZO_ARCH_AMD64 || LZO_ARCH_I386)\n#        define __ACCLIB_PCLOCK_USE_RDTSC 1\n#        define ACC_WANT_ACCLIB_RDTSC 1\n#    endif\n#endif\n#if defined(WANT_LZO_WILDARGV)\n#    define ACC_WANT_ACCLIB_WILDARGV 1\n#endif\n#if defined(__ACCLIB_PCLOCK_USE_PERFCTR)\n#    include \"src/fullacc.h\"\n#    define lzo_uclock_flush_cpu_cache(h,flags) acc_pclock_flush_cpu_cache(h,flags)\n#else\n#    include \"miniacc.h\"\n#endif\n\n#if (__ACCLIB_REQUIRE_HMEMCPY_CH) && !defined(__ACCLIB_HMEMCPY_CH_INCLUDED)\n#    define ACC_WANT_ACCLIB_HMEMCPY 1\n#    include \"src/miniacc.h\"\n#endif\n\n/*************************************************************************\n// finally pull into the LZO namespace\n**************************************************************************/\n\n#undef lzo_malloc\n#undef lzo_free\n#undef lzo_fread\n#undef lzo_fwrite\n#if defined(WANT_LZO_MALLOC)\n#    define lzo_malloc(a)         acc_halloc(a)\n#    define lzo_free(a)           acc_hfree(a)\n#endif\n#if defined(WANT_LZO_FREAD)\n#    define lzo_fread(f,b,s)      acc_hfread(f,b,s)\n#    define lzo_fwrite(f,b,s)     acc_hfwrite(f,b,s)\n#endif\n#if defined(WANT_LZO_UCLOCK)\n#    define lzo_uclock_handle_t   acc_pclock_handle_t\n#    define lzo_uclock_t          acc_pclock_t\n#    define lzo_uclock_open(a)    acc_pclock_open_default(a)\n#    define lzo_uclock_close(a)   acc_pclock_close(a)\n#    define lzo_uclock_read(a,b)  acc_pclock_read(a,b)\n#    define lzo_uclock_get_elapsed(a,b,c) acc_pclock_get_elapsed(a,b,c)\n#endif\n#if defined(WANT_LZO_WILDARGV)\n#    define lzo_wildargv(a,b)     acc_wildargv(a,b)\n#endif\n\n/*\nvi:ts=4:et\n*/\n"
  },
  {
    "path": "include/main.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n\n#ifndef __MAIN_H\n#define __MAIN_H\n#include \"config.h\"\nint handle_file(const char *file, config_opts_t *config_opts);\n#endif //__MAIN_H\n"
  },
  {
    "path": "include/mediatek.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * All right reserved\n */\n\n#ifndef __MEDIATEK_H\n#define __MEDIATEK_H\n#include <stdint.h>\n#include <elf.h>\n\n#include \"mfile.h\"\n\n#define MTK_ROM_MAGIC \"MTK/DTV/ROMCODE/NANDBOOT\" //CPU ROM (maybe unsused if boot can occur on eMMC directly)\n#define MTK_ROM_SIZE 0x4000 //16kb\n#define MTK_PBL_MAGIC \"MTK/DTV/ROMCODE/MSDCBOOT\" //First Bootloader (MSDC: Mediatek SD Controller, eMMC)\n#define MTK_PBL_SIZE 0x9FFF\n#define MTK_LOADER_OFF 0xA040\n#define MTK_LOADER_OFF1 0x4040\n#define MTK_UBOOT_OFF 0x80000\n\n#define MTK_HISENSE_UBOOT_OFF 0xA0000\n\n#define MTK_ENV_SIZE 0x20000\n#define MTK_TZ_OFF 0x200 //512\n\nvoid extract_mtk_1bl(MFILE *in, const char *outname);\nvoid split_mtk_tz(MFILE *tz, const char *destdir);\nMFILE *is_mtk_boot(const char *filename);\nint is_elf_mem(Elf32_Ehdr * header);\nMFILE *is_elf(const char *filename);\n\n#endif\n"
  },
  {
    "path": "include/mediatek_pkg.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n\n#ifndef __MTKPKG_H\n#define __MTKPKG_H\n#include \"config.h\"\n\n#define UPG_HEADER_SIZE 0x70\n\n/* Vendor Magics (all 4 bytes) */\n#define HISENSE_PKG_MAGIC \"hise\"\n#define SHARP_PKG_MAGIC \"Shar\"\n#define TPV_PKG_MAGIC \"TPV_\"\n#define TPV_PKG_MAGIC2 \"TPV\\0\"\n#define PHILIPS_PKG_MAGIC \"PHIL\"\n#define PHILIPS_PKG_MAGIC2 \"Phil\"\n\n#define PHILIPS_HEADER_SIZE 0x80 //at top before MTK header\n#define PHILIPS_SIGNATURE_SIZE 0x100 //RSA-2048 at the bottom\n\n#define MTK_FIRMWARE_MAGIC \"#DH@FiRm\" //after vendor magic\n#define MTK_RESERVED_MAGIC \"reserved mtk inc\"\n\n#define MTK_PAK_MAGIC \"iMtK8\"\n#define MTK_PAD_MAGIC \"iPAd\"\n#define MTK_EXTHDR_SIZE 64\n\n#define PAK_FLAG_ENCRYPTED (1 << 0)\n#define MTK_EXT_LZHS_OFFSET 0x100000\n#define SHARP_PKG_HEADER_SIZE 0x40\n\nstruct __attribute__((packed)) mtkupg_header {\n\tint8_t vendor_magic[4];\n\tint8_t mtk_magic[8]; //MTK_FIRMWARE_MAGIC\n\tint8_t vendor_info[60]; //version and other stuff\n\tuint32_t fileSize;\n\tuint32_t platform; //0x50 on sharp. Platform type? (unsure)\n\tint8_t product_name[40];\n\tuint32_t unk; //0x51\n\tuint32_t unk1; //0\n\tuint8_t hmac[16];\n};\n\nstruct mtkpkg_plat {\n\tchar platform[8];\n\tuint32_t otaID_len;\n\tchar otaID[];\n};\n\nstruct mtkpkg_pad {\n\tchar magic[8];\n\tuint8_t padding[];\n};\n\nstruct __attribute__((packed)) mtkpkg_crypted_header {\n\tuint8_t mtk_reserved[16]; //MTK_RESERVED_MAGIC\n\tuint8_t hmac[16];\n\tuint8_t vendor_reserved[16];\n};\n\nstruct __attribute__((packed)) mtkpkg_data {\n\tstruct mtkpkg_crypted_header header;\n\tunion {\n\t\tstruct mtkpkg_plat platform; //package header, followed by optional mtkpkg_pad\n\t\tuint8_t pkgData[0]; //first package doesn't have headers\n\t} data;\n};\n\nstruct __attribute__((packed)) mtkpkg_header {\n\tchar pakName[4];\n\tuint32_t flags;\n\tuint32_t pakSize; //including any extra header, if present\n};\n\nstruct __attribute__((packed)) mtkpkg {\n\tstruct mtkpkg_header header;\n\tstruct mtkpkg_data content;\n};\n\nMFILE *is_mtk_pkg(const char *pkgfile);\nMFILE *is_lzhs_fs(const char *pkg);\nMFILE *is_firm_image(const char *pkg);\nvoid extract_mtk_pkg(const char *pkgFile, config_opts_t *config_opts);\nvoid extract_lzhs_fs(MFILE *mf, const char *dest_file, config_opts_t *config_opts);\nint extract_firm_image(MFILE *mf);\n#endif\n"
  },
  {
    "path": "include/mfile.h",
    "content": "/*\n\tA mmap file wrapper\n\tCopyright 2016 Smx\n*/\n#ifndef __MFILE_H\n#define __MFILE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdio.h>\n#include <stdint.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/mman.h>\n\n#define MFILE_ANON(size) \\\n\tmmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0)\n\n/* Gets the size of the memory mapped file */\n#define msize(mfile) mfile->statBuf.st_size\n/* Gets the data, casted to the type specified in the second argument */\n#define mdata(mfile, type) ((type *)(mfile->pMem))\n/* Gets the file handler (for mfopen) */\n#define mfh(mfile) mfile->fh\n/* Gets the file offset */\n#define moff(mfile, ptr) (off_t)((uintptr_t)ptr - (uintptr_t)(mfile->pMem))\n\n#define mwriteat(mfile, off, ptr, size) \\\n\tmemcpy( \\\n\t\t(void *)(&(mdata(mfile, uint8_t))[off]), \\\n\t\t(void *)ptr, \\\n\t\tsize \\\n\t)\n\n#define mwrite(ptr, size, nmemb, mfile) \\\n\tmwriteat( \\\n\t\tmfile, \\\n\t\tmfile->offset, \\\n\t\tptr, \\\n\t\t(size * nmemb) \\\n\t); \\\n\tmfile->offset += (size * nmemb)\n\n#define mrewind(mfile) mfile->offset = 0\n\ntypedef struct {\n\tuint8_t *ptr;\n\toff_t offset;\n\tsize_t size;\n} cursor_t;\n\ntypedef struct {\n\tchar *path;\n\tint fd;\n\tFILE *fh;\n\toff_t offset;\n\tint prot;\n\tstruct stat statBuf;\n\tvoid *pMem;\n} MFILE;\n\nMFILE *mfile_new();\n\nvoid *mfile_map(MFILE *file, size_t size);\nvoid *mfile_map_private(MFILE *file, size_t size);\n\nMFILE *mopen(const char *path, int oflags);\nMFILE *mopen_private(const char *path, int oflags);\n\nMFILE *mfopen(const char *path, const char *mode);\nMFILE *mfopen_private(const char *path, const char *mode);\n\nvoid mfile_flush(void *mem, size_t length);\n\nint mgetc(MFILE *stream);\nint mputc(int c, MFILE *stream);\n\nint cgetc(cursor_t *stream);\nint cputc(int c, cursor_t *stream);\n\nint mclose(MFILE *mfile);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/minigzip.h",
    "content": "#ifndef MINIGZIP_H\n#define MINIGZIP_H\n#include <zlib.h>\n\nvoid error(const char *msg);\nvoid gz_compress(FILE * in, gzFile out);\n#ifdef USE_MMAP\nint gz_compress_mmap(FILE * in, gzFile out);\n#endif\nvoid gz_uncompress(gzFile in, FILE * out);\nvoid file_compress(char *file, char *mode);\nvoid file_uncompress(char *infile, char *outfile);\nchar *file_uncompress_origname(char *infile, char *path);\n\n#endif /* MINIGZIP_H */\n"
  },
  {
    "path": "include/os_byteswap.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#ifndef BYTESWAP_H\n#define\tBYTESWAP_H\n\n#define SWAP(x) SwapBytes(&x, sizeof(x))\n\n#ifdef __APPLE__\n#\tinclude <libkern/OSByteOrder.h>\n#\tdefine bswap_16(x) OSSwapInt16(x)\n#\tdefine bswap_32(x) OSSwapInt32(x)\n#else\n#\tinclude <byteswap.h>\n#endif\n\nvoid SwapBytes(void *pv, size_t n);\n#endif /* BYTESWAP_H */\n"
  },
  {
    "path": "include/osx/elf.h",
    "content": "/* This is the original elf.h file from the GNU C Library; I only removed\n   the inclusion of feature.h, which is not needed.\n\n   On OSX, simply copy the file to /usr/local/include/.\n\n   Mathias Lafeldt <mathias.lafeldt@gmail.com> */\n\n/* This file defines standard ELF types, structures, and macros.\n   Copyright (C) 1995-2003,2004,2005,2006,2007,2008,2009,2010,2011\n\tFree Software Foundation, Inc.\n   This file is part of the GNU C Library.\n\n   The GNU C Library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   The GNU C Library 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 GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with the GNU C Library; if not, write to the Free\n   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA\n   02111-1307 USA.  */\n\n#ifndef _ELF_H\n#define\t_ELF_H 1\n\n__BEGIN_DECLS\n\n/* Standard ELF types.  */\n\n#include <stdint.h>\n\n/* Type for a 16-bit quantity.  */\ntypedef uint16_t Elf32_Half;\ntypedef uint16_t Elf64_Half;\n\n/* Types for signed and unsigned 32-bit quantities.  */\ntypedef uint32_t Elf32_Word;\ntypedef\tint32_t  Elf32_Sword;\ntypedef uint32_t Elf64_Word;\ntypedef\tint32_t  Elf64_Sword;\n\n/* Types for signed and unsigned 64-bit quantities.  */\ntypedef uint64_t Elf32_Xword;\ntypedef\tint64_t  Elf32_Sxword;\ntypedef uint64_t Elf64_Xword;\ntypedef\tint64_t  Elf64_Sxword;\n\n/* Type of addresses.  */\ntypedef uint32_t Elf32_Addr;\ntypedef uint64_t Elf64_Addr;\n\n/* Type of file offsets.  */\ntypedef uint32_t Elf32_Off;\ntypedef uint64_t Elf64_Off;\n\n/* Type for section indices, which are 16-bit quantities.  */\ntypedef uint16_t Elf32_Section;\ntypedef uint16_t Elf64_Section;\n\n/* Type for version symbol information.  */\ntypedef Elf32_Half Elf32_Versym;\ntypedef Elf64_Half Elf64_Versym;\n\n\n/* The ELF file header.  This appears at the start of every ELF file.  */\n\n#define EI_NIDENT (16)\n\ntypedef struct\n{\n  unsigned char\te_ident[EI_NIDENT];\t/* Magic number and other info */\n  Elf32_Half\te_type;\t\t\t/* Object file type */\n  Elf32_Half\te_machine;\t\t/* Architecture */\n  Elf32_Word\te_version;\t\t/* Object file version */\n  Elf32_Addr\te_entry;\t\t/* Entry point virtual address */\n  Elf32_Off\te_phoff;\t\t/* Program header table file offset */\n  Elf32_Off\te_shoff;\t\t/* Section header table file offset */\n  Elf32_Word\te_flags;\t\t/* Processor-specific flags */\n  Elf32_Half\te_ehsize;\t\t/* ELF header size in bytes */\n  Elf32_Half\te_phentsize;\t\t/* Program header table entry size */\n  Elf32_Half\te_phnum;\t\t/* Program header table entry count */\n  Elf32_Half\te_shentsize;\t\t/* Section header table entry size */\n  Elf32_Half\te_shnum;\t\t/* Section header table entry count */\n  Elf32_Half\te_shstrndx;\t\t/* Section header string table index */\n} Elf32_Ehdr;\n\ntypedef struct\n{\n  unsigned char\te_ident[EI_NIDENT];\t/* Magic number and other info */\n  Elf64_Half\te_type;\t\t\t/* Object file type */\n  Elf64_Half\te_machine;\t\t/* Architecture */\n  Elf64_Word\te_version;\t\t/* Object file version */\n  Elf64_Addr\te_entry;\t\t/* Entry point virtual address */\n  Elf64_Off\te_phoff;\t\t/* Program header table file offset */\n  Elf64_Off\te_shoff;\t\t/* Section header table file offset */\n  Elf64_Word\te_flags;\t\t/* Processor-specific flags */\n  Elf64_Half\te_ehsize;\t\t/* ELF header size in bytes */\n  Elf64_Half\te_phentsize;\t\t/* Program header table entry size */\n  Elf64_Half\te_phnum;\t\t/* Program header table entry count */\n  Elf64_Half\te_shentsize;\t\t/* Section header table entry size */\n  Elf64_Half\te_shnum;\t\t/* Section header table entry count */\n  Elf64_Half\te_shstrndx;\t\t/* Section header string table index */\n} Elf64_Ehdr;\n\n/* Fields in the e_ident array.  The EI_* macros are indices into the\n   array.  The macros under each EI_* macro are the values the byte\n   may have.  */\n\n#define EI_MAG0\t\t0\t\t/* File identification byte 0 index */\n#define ELFMAG0\t\t0x7f\t\t/* Magic number byte 0 */\n\n#define EI_MAG1\t\t1\t\t/* File identification byte 1 index */\n#define ELFMAG1\t\t'E'\t\t/* Magic number byte 1 */\n\n#define EI_MAG2\t\t2\t\t/* File identification byte 2 index */\n#define ELFMAG2\t\t'L'\t\t/* Magic number byte 2 */\n\n#define EI_MAG3\t\t3\t\t/* File identification byte 3 index */\n#define ELFMAG3\t\t'F'\t\t/* Magic number byte 3 */\n\n/* Conglomeration of the identification bytes, for easy testing as a word.  */\n#define\tELFMAG\t\t\"\\177ELF\"\n#define\tSELFMAG\t\t4\n\n#define EI_CLASS\t4\t\t/* File class byte index */\n#define ELFCLASSNONE\t0\t\t/* Invalid class */\n#define ELFCLASS32\t1\t\t/* 32-bit objects */\n#define ELFCLASS64\t2\t\t/* 64-bit objects */\n#define ELFCLASSNUM\t3\n\n#define EI_DATA\t\t5\t\t/* Data encoding byte index */\n#define ELFDATANONE\t0\t\t/* Invalid data encoding */\n#define ELFDATA2LSB\t1\t\t/* 2's complement, little endian */\n#define ELFDATA2MSB\t2\t\t/* 2's complement, big endian */\n#define ELFDATANUM\t3\n\n#define EI_VERSION\t6\t\t/* File version byte index */\n\t\t\t\t\t/* Value must be EV_CURRENT */\n\n#define EI_OSABI\t7\t\t/* OS ABI identification */\n#define ELFOSABI_NONE\t\t0\t/* UNIX System V ABI */\n#define ELFOSABI_SYSV\t\t0\t/* Alias.  */\n#define ELFOSABI_HPUX\t\t1\t/* HP-UX */\n#define ELFOSABI_NETBSD\t\t2\t/* NetBSD.  */\n#define ELFOSABI_GNU\t\t3\t/* Object uses GNU ELF extensions.  */\n#define ELFOSABI_LINUX\t\tELFOSABI_GNU /* Compatibility alias.  */\n#define ELFOSABI_SOLARIS\t6\t/* Sun Solaris.  */\n#define ELFOSABI_AIX\t\t7\t/* IBM AIX.  */\n#define ELFOSABI_IRIX\t\t8\t/* SGI Irix.  */\n#define ELFOSABI_FREEBSD\t9\t/* FreeBSD.  */\n#define ELFOSABI_TRU64\t\t10\t/* Compaq TRU64 UNIX.  */\n#define ELFOSABI_MODESTO\t11\t/* Novell Modesto.  */\n#define ELFOSABI_OPENBSD\t12\t/* OpenBSD.  */\n#define ELFOSABI_ARM_AEABI\t64\t/* ARM EABI */\n#define ELFOSABI_ARM\t\t97\t/* ARM */\n#define ELFOSABI_STANDALONE\t255\t/* Standalone (embedded) application */\n\n#define EI_ABIVERSION\t8\t\t/* ABI version */\n\n#define EI_PAD\t\t9\t\t/* Byte index of padding bytes */\n\n/* Legal values for e_type (object file type).  */\n\n#define ET_NONE\t\t0\t\t/* No file type */\n#define ET_REL\t\t1\t\t/* Relocatable file */\n#define ET_EXEC\t\t2\t\t/* Executable file */\n#define ET_DYN\t\t3\t\t/* Shared object file */\n#define ET_CORE\t\t4\t\t/* Core file */\n#define\tET_NUM\t\t5\t\t/* Number of defined types */\n#define ET_LOOS\t\t0xfe00\t\t/* OS-specific range start */\n#define ET_HIOS\t\t0xfeff\t\t/* OS-specific range end */\n#define ET_LOPROC\t0xff00\t\t/* Processor-specific range start */\n#define ET_HIPROC\t0xffff\t\t/* Processor-specific range end */\n\n/* Legal values for e_machine (architecture).  */\n\n#define EM_NONE\t\t 0\t\t/* No machine */\n#define EM_M32\t\t 1\t\t/* AT&T WE 32100 */\n#define EM_SPARC\t 2\t\t/* SUN SPARC */\n#define EM_386\t\t 3\t\t/* Intel 80386 */\n#define EM_68K\t\t 4\t\t/* Motorola m68k family */\n#define EM_88K\t\t 5\t\t/* Motorola m88k family */\n#define EM_860\t\t 7\t\t/* Intel 80860 */\n#define EM_MIPS\t\t 8\t\t/* MIPS R3000 big-endian */\n#define EM_S370\t\t 9\t\t/* IBM System/370 */\n#define EM_MIPS_RS3_LE\t10\t\t/* MIPS R3000 little-endian */\n\n#define EM_PARISC\t15\t\t/* HPPA */\n#define EM_VPP500\t17\t\t/* Fujitsu VPP500 */\n#define EM_SPARC32PLUS\t18\t\t/* Sun's \"v8plus\" */\n#define EM_960\t\t19\t\t/* Intel 80960 */\n#define EM_PPC\t\t20\t\t/* PowerPC */\n#define EM_PPC64\t21\t\t/* PowerPC 64-bit */\n#define EM_S390\t\t22\t\t/* IBM S390 */\n\n#define EM_V800\t\t36\t\t/* NEC V800 series */\n#define EM_FR20\t\t37\t\t/* Fujitsu FR20 */\n#define EM_RH32\t\t38\t\t/* TRW RH-32 */\n#define EM_RCE\t\t39\t\t/* Motorola RCE */\n#define EM_ARM\t\t40\t\t/* ARM */\n#define EM_FAKE_ALPHA\t41\t\t/* Digital Alpha */\n#define EM_SH\t\t42\t\t/* Hitachi SH */\n#define EM_SPARCV9\t43\t\t/* SPARC v9 64-bit */\n#define EM_TRICORE\t44\t\t/* Siemens Tricore */\n#define EM_ARC\t\t45\t\t/* Argonaut RISC Core */\n#define EM_H8_300\t46\t\t/* Hitachi H8/300 */\n#define EM_H8_300H\t47\t\t/* Hitachi H8/300H */\n#define EM_H8S\t\t48\t\t/* Hitachi H8S */\n#define EM_H8_500\t49\t\t/* Hitachi H8/500 */\n#define EM_IA_64\t50\t\t/* Intel Merced */\n#define EM_MIPS_X\t51\t\t/* Stanford MIPS-X */\n#define EM_COLDFIRE\t52\t\t/* Motorola Coldfire */\n#define EM_68HC12\t53\t\t/* Motorola M68HC12 */\n#define EM_MMA\t\t54\t\t/* Fujitsu MMA Multimedia Accelerator*/\n#define EM_PCP\t\t55\t\t/* Siemens PCP */\n#define EM_NCPU\t\t56\t\t/* Sony nCPU embeeded RISC */\n#define EM_NDR1\t\t57\t\t/* Denso NDR1 microprocessor */\n#define EM_STARCORE\t58\t\t/* Motorola Start*Core processor */\n#define EM_ME16\t\t59\t\t/* Toyota ME16 processor */\n#define EM_ST100\t60\t\t/* STMicroelectronic ST100 processor */\n#define EM_TINYJ\t61\t\t/* Advanced Logic Corp. Tinyj emb.fam*/\n#define EM_X86_64\t62\t\t/* AMD x86-64 architecture */\n#define EM_PDSP\t\t63\t\t/* Sony DSP Processor */\n\n#define EM_FX66\t\t66\t\t/* Siemens FX66 microcontroller */\n#define EM_ST9PLUS\t67\t\t/* STMicroelectronics ST9+ 8/16 mc */\n#define EM_ST7\t\t68\t\t/* STmicroelectronics ST7 8 bit mc */\n#define EM_68HC16\t69\t\t/* Motorola MC68HC16 microcontroller */\n#define EM_68HC11\t70\t\t/* Motorola MC68HC11 microcontroller */\n#define EM_68HC08\t71\t\t/* Motorola MC68HC08 microcontroller */\n#define EM_68HC05\t72\t\t/* Motorola MC68HC05 microcontroller */\n#define EM_SVX\t\t73\t\t/* Silicon Graphics SVx */\n#define EM_ST19\t\t74\t\t/* STMicroelectronics ST19 8 bit mc */\n#define EM_VAX\t\t75\t\t/* Digital VAX */\n#define EM_CRIS\t\t76\t\t/* Axis Communications 32-bit embedded processor */\n#define EM_JAVELIN\t77\t\t/* Infineon Technologies 32-bit embedded processor */\n#define EM_FIREPATH\t78\t\t/* Element 14 64-bit DSP Processor */\n#define EM_ZSP\t\t79\t\t/* LSI Logic 16-bit DSP Processor */\n#define EM_MMIX\t\t80\t\t/* Donald Knuth's educational 64-bit processor */\n#define EM_HUANY\t81\t\t/* Harvard University machine-independent object files */\n#define EM_PRISM\t82\t\t/* SiTera Prism */\n#define EM_AVR\t\t83\t\t/* Atmel AVR 8-bit microcontroller */\n#define EM_FR30\t\t84\t\t/* Fujitsu FR30 */\n#define EM_D10V\t\t85\t\t/* Mitsubishi D10V */\n#define EM_D30V\t\t86\t\t/* Mitsubishi D30V */\n#define EM_V850\t\t87\t\t/* NEC v850 */\n#define EM_M32R\t\t88\t\t/* Mitsubishi M32R */\n#define EM_MN10300\t89\t\t/* Matsushita MN10300 */\n#define EM_MN10200\t90\t\t/* Matsushita MN10200 */\n#define EM_PJ\t\t91\t\t/* picoJava */\n#define EM_OPENRISC\t92\t\t/* OpenRISC 32-bit embedded processor */\n#define EM_ARC_A5\t93\t\t/* ARC Cores Tangent-A5 */\n#define EM_XTENSA\t94\t\t/* Tensilica Xtensa Architecture */\n#define EM_NUM\t\t95\n\n/* If it is necessary to assign new unofficial EM_* values, please\n   pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the\n   chances of collision with official or non-GNU unofficial values.  */\n\n#define EM_ALPHA\t0x9026\n\n/* Legal values for e_version (version).  */\n\n#define EV_NONE\t\t0\t\t/* Invalid ELF version */\n#define EV_CURRENT\t1\t\t/* Current version */\n#define EV_NUM\t\t2\n\n/* Section header.  */\n\ntypedef struct\n{\n  Elf32_Word\tsh_name;\t\t/* Section name (string tbl index) */\n  Elf32_Word\tsh_type;\t\t/* Section type */\n  Elf32_Word\tsh_flags;\t\t/* Section flags */\n  Elf32_Addr\tsh_addr;\t\t/* Section virtual addr at execution */\n  Elf32_Off\tsh_offset;\t\t/* Section file offset */\n  Elf32_Word\tsh_size;\t\t/* Section size in bytes */\n  Elf32_Word\tsh_link;\t\t/* Link to another section */\n  Elf32_Word\tsh_info;\t\t/* Additional section information */\n  Elf32_Word\tsh_addralign;\t\t/* Section alignment */\n  Elf32_Word\tsh_entsize;\t\t/* Entry size if section holds table */\n} Elf32_Shdr;\n\ntypedef struct\n{\n  Elf64_Word\tsh_name;\t\t/* Section name (string tbl index) */\n  Elf64_Word\tsh_type;\t\t/* Section type */\n  Elf64_Xword\tsh_flags;\t\t/* Section flags */\n  Elf64_Addr\tsh_addr;\t\t/* Section virtual addr at execution */\n  Elf64_Off\tsh_offset;\t\t/* Section file offset */\n  Elf64_Xword\tsh_size;\t\t/* Section size in bytes */\n  Elf64_Word\tsh_link;\t\t/* Link to another section */\n  Elf64_Word\tsh_info;\t\t/* Additional section information */\n  Elf64_Xword\tsh_addralign;\t\t/* Section alignment */\n  Elf64_Xword\tsh_entsize;\t\t/* Entry size if section holds table */\n} Elf64_Shdr;\n\n/* Special section indices.  */\n\n#define SHN_UNDEF\t0\t\t/* Undefined section */\n#define SHN_LORESERVE\t0xff00\t\t/* Start of reserved indices */\n#define SHN_LOPROC\t0xff00\t\t/* Start of processor-specific */\n#define SHN_BEFORE\t0xff00\t\t/* Order section before all others\n\t\t\t\t\t   (Solaris).  */\n#define SHN_AFTER\t0xff01\t\t/* Order section after all others\n\t\t\t\t\t   (Solaris).  */\n#define SHN_HIPROC\t0xff1f\t\t/* End of processor-specific */\n#define SHN_LOOS\t0xff20\t\t/* Start of OS-specific */\n#define SHN_HIOS\t0xff3f\t\t/* End of OS-specific */\n#define SHN_ABS\t\t0xfff1\t\t/* Associated symbol is absolute */\n#define SHN_COMMON\t0xfff2\t\t/* Associated symbol is common */\n#define SHN_XINDEX\t0xffff\t\t/* Index is in extra table.  */\n#define SHN_HIRESERVE\t0xffff\t\t/* End of reserved indices */\n\n/* Legal values for sh_type (section type).  */\n\n#define SHT_NULL\t  0\t\t/* Section header table entry unused */\n#define SHT_PROGBITS\t  1\t\t/* Program data */\n#define SHT_SYMTAB\t  2\t\t/* Symbol table */\n#define SHT_STRTAB\t  3\t\t/* String table */\n#define SHT_RELA\t  4\t\t/* Relocation entries with addends */\n#define SHT_HASH\t  5\t\t/* Symbol hash table */\n#define SHT_DYNAMIC\t  6\t\t/* Dynamic linking information */\n#define SHT_NOTE\t  7\t\t/* Notes */\n#define SHT_NOBITS\t  8\t\t/* Program space with no data (bss) */\n#define SHT_REL\t\t  9\t\t/* Relocation entries, no addends */\n#define SHT_SHLIB\t  10\t\t/* Reserved */\n#define SHT_DYNSYM\t  11\t\t/* Dynamic linker symbol table */\n#define SHT_INIT_ARRAY\t  14\t\t/* Array of constructors */\n#define SHT_FINI_ARRAY\t  15\t\t/* Array of destructors */\n#define SHT_PREINIT_ARRAY 16\t\t/* Array of pre-constructors */\n#define SHT_GROUP\t  17\t\t/* Section group */\n#define SHT_SYMTAB_SHNDX  18\t\t/* Extended section indeces */\n#define\tSHT_NUM\t\t  19\t\t/* Number of defined types.  */\n#define SHT_LOOS\t  0x60000000\t/* Start OS-specific.  */\n#define SHT_GNU_ATTRIBUTES 0x6ffffff5\t/* Object attributes.  */\n#define SHT_GNU_HASH\t  0x6ffffff6\t/* GNU-style hash table.  */\n#define SHT_GNU_LIBLIST\t  0x6ffffff7\t/* Prelink library list */\n#define SHT_CHECKSUM\t  0x6ffffff8\t/* Checksum for DSO content.  */\n#define SHT_LOSUNW\t  0x6ffffffa\t/* Sun-specific low bound.  */\n#define SHT_SUNW_move\t  0x6ffffffa\n#define SHT_SUNW_COMDAT   0x6ffffffb\n#define SHT_SUNW_syminfo  0x6ffffffc\n#define SHT_GNU_verdef\t  0x6ffffffd\t/* Version definition section.  */\n#define SHT_GNU_verneed\t  0x6ffffffe\t/* Version needs section.  */\n#define SHT_GNU_versym\t  0x6fffffff\t/* Version symbol table.  */\n#define SHT_HISUNW\t  0x6fffffff\t/* Sun-specific high bound.  */\n#define SHT_HIOS\t  0x6fffffff\t/* End OS-specific type */\n#define SHT_LOPROC\t  0x70000000\t/* Start of processor-specific */\n#define SHT_HIPROC\t  0x7fffffff\t/* End of processor-specific */\n#define SHT_LOUSER\t  0x80000000\t/* Start of application-specific */\n#define SHT_HIUSER\t  0x8fffffff\t/* End of application-specific */\n\n/* Legal values for sh_flags (section flags).  */\n\n#define SHF_WRITE\t     (1 << 0)\t/* Writable */\n#define SHF_ALLOC\t     (1 << 1)\t/* Occupies memory during execution */\n#define SHF_EXECINSTR\t     (1 << 2)\t/* Executable */\n#define SHF_MERGE\t     (1 << 4)\t/* Might be merged */\n#define SHF_STRINGS\t     (1 << 5)\t/* Contains nul-terminated strings */\n#define SHF_INFO_LINK\t     (1 << 6)\t/* `sh_info' contains SHT index */\n#define SHF_LINK_ORDER\t     (1 << 7)\t/* Preserve order after combining */\n#define SHF_OS_NONCONFORMING (1 << 8)\t/* Non-standard OS specific handling\n\t\t\t\t\t   required */\n#define SHF_GROUP\t     (1 << 9)\t/* Section is member of a group.  */\n#define SHF_TLS\t\t     (1 << 10)\t/* Section hold thread-local data.  */\n#define SHF_MASKOS\t     0x0ff00000\t/* OS-specific.  */\n#define SHF_MASKPROC\t     0xf0000000\t/* Processor-specific */\n#define SHF_ORDERED\t     (1 << 30)\t/* Special ordering requirement\n\t\t\t\t\t   (Solaris).  */\n#define SHF_EXCLUDE\t     (1 << 31)\t/* Section is excluded unless\n\t\t\t\t\t   referenced or allocated (Solaris).*/\n\n/* Section group handling.  */\n#define GRP_COMDAT\t0x1\t\t/* Mark group as COMDAT.  */\n\n/* Symbol table entry.  */\n\ntypedef struct\n{\n  Elf32_Word\tst_name;\t\t/* Symbol name (string tbl index) */\n  Elf32_Addr\tst_value;\t\t/* Symbol value */\n  Elf32_Word\tst_size;\t\t/* Symbol size */\n  unsigned char\tst_info;\t\t/* Symbol type and binding */\n  unsigned char\tst_other;\t\t/* Symbol visibility */\n  Elf32_Section\tst_shndx;\t\t/* Section index */\n} Elf32_Sym;\n\ntypedef struct\n{\n  Elf64_Word\tst_name;\t\t/* Symbol name (string tbl index) */\n  unsigned char\tst_info;\t\t/* Symbol type and binding */\n  unsigned char st_other;\t\t/* Symbol visibility */\n  Elf64_Section\tst_shndx;\t\t/* Section index */\n  Elf64_Addr\tst_value;\t\t/* Symbol value */\n  Elf64_Xword\tst_size;\t\t/* Symbol size */\n} Elf64_Sym;\n\n/* The syminfo section if available contains additional information about\n   every dynamic symbol.  */\n\ntypedef struct\n{\n  Elf32_Half si_boundto;\t\t/* Direct bindings, symbol bound to */\n  Elf32_Half si_flags;\t\t\t/* Per symbol flags */\n} Elf32_Syminfo;\n\ntypedef struct\n{\n  Elf64_Half si_boundto;\t\t/* Direct bindings, symbol bound to */\n  Elf64_Half si_flags;\t\t\t/* Per symbol flags */\n} Elf64_Syminfo;\n\n/* Possible values for si_boundto.  */\n#define SYMINFO_BT_SELF\t\t0xffff\t/* Symbol bound to self */\n#define SYMINFO_BT_PARENT\t0xfffe\t/* Symbol bound to parent */\n#define SYMINFO_BT_LOWRESERVE\t0xff00\t/* Beginning of reserved entries */\n\n/* Possible bitmasks for si_flags.  */\n#define SYMINFO_FLG_DIRECT\t0x0001\t/* Direct bound symbol */\n#define SYMINFO_FLG_PASSTHRU\t0x0002\t/* Pass-thru symbol for translator */\n#define SYMINFO_FLG_COPY\t0x0004\t/* Symbol is a copy-reloc */\n#define SYMINFO_FLG_LAZYLOAD\t0x0008\t/* Symbol bound to object to be lazy\n\t\t\t\t\t   loaded */\n/* Syminfo version values.  */\n#define SYMINFO_NONE\t\t0\n#define SYMINFO_CURRENT\t\t1\n#define SYMINFO_NUM\t\t2\n\n\n/* How to extract and insert information held in the st_info field.  */\n\n#define ELF32_ST_BIND(val)\t\t(((unsigned char) (val)) >> 4)\n#define ELF32_ST_TYPE(val)\t\t((val) & 0xf)\n#define ELF32_ST_INFO(bind, type)\t(((bind) << 4) + ((type) & 0xf))\n\n/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field.  */\n#define ELF64_ST_BIND(val)\t\tELF32_ST_BIND (val)\n#define ELF64_ST_TYPE(val)\t\tELF32_ST_TYPE (val)\n#define ELF64_ST_INFO(bind, type)\tELF32_ST_INFO ((bind), (type))\n\n/* Legal values for ST_BIND subfield of st_info (symbol binding).  */\n\n#define STB_LOCAL\t0\t\t/* Local symbol */\n#define STB_GLOBAL\t1\t\t/* Global symbol */\n#define STB_WEAK\t2\t\t/* Weak symbol */\n#define\tSTB_NUM\t\t3\t\t/* Number of defined types.  */\n#define STB_LOOS\t10\t\t/* Start of OS-specific */\n#define STB_GNU_UNIQUE\t10\t\t/* Unique symbol.  */\n#define STB_HIOS\t12\t\t/* End of OS-specific */\n#define STB_LOPROC\t13\t\t/* Start of processor-specific */\n#define STB_HIPROC\t15\t\t/* End of processor-specific */\n\n/* Legal values for ST_TYPE subfield of st_info (symbol type).  */\n\n#define STT_NOTYPE\t0\t\t/* Symbol type is unspecified */\n#define STT_OBJECT\t1\t\t/* Symbol is a data object */\n#define STT_FUNC\t2\t\t/* Symbol is a code object */\n#define STT_SECTION\t3\t\t/* Symbol associated with a section */\n#define STT_FILE\t4\t\t/* Symbol's name is file name */\n#define STT_COMMON\t5\t\t/* Symbol is a common data object */\n#define STT_TLS\t\t6\t\t/* Symbol is thread-local data object*/\n#define\tSTT_NUM\t\t7\t\t/* Number of defined types.  */\n#define STT_LOOS\t10\t\t/* Start of OS-specific */\n#define STT_GNU_IFUNC\t10\t\t/* Symbol is indirect code object */\n#define STT_HIOS\t12\t\t/* End of OS-specific */\n#define STT_LOPROC\t13\t\t/* Start of processor-specific */\n#define STT_HIPROC\t15\t\t/* End of processor-specific */\n\n\n/* Symbol table indices are found in the hash buckets and chain table\n   of a symbol hash table section.  This special index value indicates\n   the end of a chain, meaning no further symbols are found in that bucket.  */\n\n#define STN_UNDEF\t0\t\t/* End of a chain.  */\n\n\n/* How to extract and insert information held in the st_other field.  */\n\n#define ELF32_ST_VISIBILITY(o)\t((o) & 0x03)\n\n/* For ELF64 the definitions are the same.  */\n#define ELF64_ST_VISIBILITY(o)\tELF32_ST_VISIBILITY (o)\n\n/* Symbol visibility specification encoded in the st_other field.  */\n#define STV_DEFAULT\t0\t\t/* Default symbol visibility rules */\n#define STV_INTERNAL\t1\t\t/* Processor specific hidden class */\n#define STV_HIDDEN\t2\t\t/* Sym unavailable in other modules */\n#define STV_PROTECTED\t3\t\t/* Not preemptible, not exported */\n\n\n/* Relocation table entry without addend (in section of type SHT_REL).  */\n\ntypedef struct\n{\n  Elf32_Addr\tr_offset;\t\t/* Address */\n  Elf32_Word\tr_info;\t\t\t/* Relocation type and symbol index */\n} Elf32_Rel;\n\n/* I have seen two different definitions of the Elf64_Rel and\n   Elf64_Rela structures, so we'll leave them out until Novell (or\n   whoever) gets their act together.  */\n/* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */\n\ntypedef struct\n{\n  Elf64_Addr\tr_offset;\t\t/* Address */\n  Elf64_Xword\tr_info;\t\t\t/* Relocation type and symbol index */\n} Elf64_Rel;\n\n/* Relocation table entry with addend (in section of type SHT_RELA).  */\n\ntypedef struct\n{\n  Elf32_Addr\tr_offset;\t\t/* Address */\n  Elf32_Word\tr_info;\t\t\t/* Relocation type and symbol index */\n  Elf32_Sword\tr_addend;\t\t/* Addend */\n} Elf32_Rela;\n\ntypedef struct\n{\n  Elf64_Addr\tr_offset;\t\t/* Address */\n  Elf64_Xword\tr_info;\t\t\t/* Relocation type and symbol index */\n  Elf64_Sxword\tr_addend;\t\t/* Addend */\n} Elf64_Rela;\n\n/* How to extract and insert information held in the r_info field.  */\n\n#define ELF32_R_SYM(val)\t\t((val) >> 8)\n#define ELF32_R_TYPE(val)\t\t((val) & 0xff)\n#define ELF32_R_INFO(sym, type)\t\t(((sym) << 8) + ((type) & 0xff))\n\n#define ELF64_R_SYM(i)\t\t\t((i) >> 32)\n#define ELF64_R_TYPE(i)\t\t\t((i) & 0xffffffff)\n#define ELF64_R_INFO(sym,type)\t\t((((Elf64_Xword) (sym)) << 32) + (type))\n\n/* Program segment header.  */\n\ntypedef struct\n{\n  Elf32_Word\tp_type;\t\t\t/* Segment type */\n  Elf32_Off\tp_offset;\t\t/* Segment file offset */\n  Elf32_Addr\tp_vaddr;\t\t/* Segment virtual address */\n  Elf32_Addr\tp_paddr;\t\t/* Segment physical address */\n  Elf32_Word\tp_filesz;\t\t/* Segment size in file */\n  Elf32_Word\tp_memsz;\t\t/* Segment size in memory */\n  Elf32_Word\tp_flags;\t\t/* Segment flags */\n  Elf32_Word\tp_align;\t\t/* Segment alignment */\n} Elf32_Phdr;\n\ntypedef struct\n{\n  Elf64_Word\tp_type;\t\t\t/* Segment type */\n  Elf64_Word\tp_flags;\t\t/* Segment flags */\n  Elf64_Off\tp_offset;\t\t/* Segment file offset */\n  Elf64_Addr\tp_vaddr;\t\t/* Segment virtual address */\n  Elf64_Addr\tp_paddr;\t\t/* Segment physical address */\n  Elf64_Xword\tp_filesz;\t\t/* Segment size in file */\n  Elf64_Xword\tp_memsz;\t\t/* Segment size in memory */\n  Elf64_Xword\tp_align;\t\t/* Segment alignment */\n} Elf64_Phdr;\n\n/* Special value for e_phnum.  This indicates that the real number of\n   program headers is too large to fit into e_phnum.  Instead the real\n   value is in the field sh_info of section 0.  */\n\n#define PN_XNUM\t\t0xffff\n\n/* Legal values for p_type (segment type).  */\n\n#define\tPT_NULL\t\t0\t\t/* Program header table entry unused */\n#define PT_LOAD\t\t1\t\t/* Loadable program segment */\n#define PT_DYNAMIC\t2\t\t/* Dynamic linking information */\n#define PT_INTERP\t3\t\t/* Program interpreter */\n#define PT_NOTE\t\t4\t\t/* Auxiliary information */\n#define PT_SHLIB\t5\t\t/* Reserved */\n#define PT_PHDR\t\t6\t\t/* Entry for header table itself */\n#define PT_TLS\t\t7\t\t/* Thread-local storage segment */\n#define\tPT_NUM\t\t8\t\t/* Number of defined types */\n#define PT_LOOS\t\t0x60000000\t/* Start of OS-specific */\n#define PT_GNU_EH_FRAME\t0x6474e550\t/* GCC .eh_frame_hdr segment */\n#define PT_GNU_STACK\t0x6474e551\t/* Indicates stack executability */\n#define PT_GNU_RELRO\t0x6474e552\t/* Read-only after relocation */\n#define PT_LOSUNW\t0x6ffffffa\n#define PT_SUNWBSS\t0x6ffffffa\t/* Sun Specific segment */\n#define PT_SUNWSTACK\t0x6ffffffb\t/* Stack segment */\n#define PT_HISUNW\t0x6fffffff\n#define PT_HIOS\t\t0x6fffffff\t/* End of OS-specific */\n#define PT_LOPROC\t0x70000000\t/* Start of processor-specific */\n#define PT_HIPROC\t0x7fffffff\t/* End of processor-specific */\n\n/* Legal values for p_flags (segment flags).  */\n\n#define PF_X\t\t(1 << 0)\t/* Segment is executable */\n#define PF_W\t\t(1 << 1)\t/* Segment is writable */\n#define PF_R\t\t(1 << 2)\t/* Segment is readable */\n#define PF_MASKOS\t0x0ff00000\t/* OS-specific */\n#define PF_MASKPROC\t0xf0000000\t/* Processor-specific */\n\n/* Legal values for note segment descriptor types for core files. */\n\n#define NT_PRSTATUS\t1\t\t/* Contains copy of prstatus struct */\n#define NT_FPREGSET\t2\t\t/* Contains copy of fpregset struct */\n#define NT_PRPSINFO\t3\t\t/* Contains copy of prpsinfo struct */\n#define NT_PRXREG\t4\t\t/* Contains copy of prxregset struct */\n#define NT_TASKSTRUCT\t4\t\t/* Contains copy of task structure */\n#define NT_PLATFORM\t5\t\t/* String from sysinfo(SI_PLATFORM) */\n#define NT_AUXV\t\t6\t\t/* Contains copy of auxv array */\n#define NT_GWINDOWS\t7\t\t/* Contains copy of gwindows struct */\n#define NT_ASRS\t\t8\t\t/* Contains copy of asrset struct */\n#define NT_PSTATUS\t10\t\t/* Contains copy of pstatus struct */\n#define NT_PSINFO\t13\t\t/* Contains copy of psinfo struct */\n#define NT_PRCRED\t14\t\t/* Contains copy of prcred struct */\n#define NT_UTSNAME\t15\t\t/* Contains copy of utsname struct */\n#define NT_LWPSTATUS\t16\t\t/* Contains copy of lwpstatus struct */\n#define NT_LWPSINFO\t17\t\t/* Contains copy of lwpinfo struct */\n#define NT_PRFPXREG\t20\t\t/* Contains copy of fprxregset struct */\n#define NT_PRXFPREG\t0x46e62b7f\t/* Contains copy of user_fxsr_struct */\n#define NT_PPC_VMX\t0x100\t\t/* PowerPC Altivec/VMX registers */\n#define NT_PPC_SPE\t0x101\t\t/* PowerPC SPE/EVR registers */\n#define NT_PPC_VSX\t0x102\t\t/* PowerPC VSX registers */\n#define NT_386_TLS\t0x200\t\t/* i386 TLS slots (struct user_desc) */\n#define NT_386_IOPERM\t0x201\t\t/* x86 io permission bitmap (1=deny) */\n#define NT_X86_XSTATE\t0x202\t\t/* x86 extended state using xsave */\n\n/* Legal values for the note segment descriptor types for object files.  */\n\n#define NT_VERSION\t1\t\t/* Contains a version string.  */\n\n\n/* Dynamic section entry.  */\n\ntypedef struct\n{\n  Elf32_Sword\td_tag;\t\t\t/* Dynamic entry type */\n  union\n    {\n      Elf32_Word d_val;\t\t\t/* Integer value */\n      Elf32_Addr d_ptr;\t\t\t/* Address value */\n    } d_un;\n} Elf32_Dyn;\n\ntypedef struct\n{\n  Elf64_Sxword\td_tag;\t\t\t/* Dynamic entry type */\n  union\n    {\n      Elf64_Xword d_val;\t\t/* Integer value */\n      Elf64_Addr d_ptr;\t\t\t/* Address value */\n    } d_un;\n} Elf64_Dyn;\n\n/* Legal values for d_tag (dynamic entry type).  */\n\n#define DT_NULL\t\t0\t\t/* Marks end of dynamic section */\n#define DT_NEEDED\t1\t\t/* Name of needed library */\n#define DT_PLTRELSZ\t2\t\t/* Size in bytes of PLT relocs */\n#define DT_PLTGOT\t3\t\t/* Processor defined value */\n#define DT_HASH\t\t4\t\t/* Address of symbol hash table */\n#define DT_STRTAB\t5\t\t/* Address of string table */\n#define DT_SYMTAB\t6\t\t/* Address of symbol table */\n#define DT_RELA\t\t7\t\t/* Address of Rela relocs */\n#define DT_RELASZ\t8\t\t/* Total size of Rela relocs */\n#define DT_RELAENT\t9\t\t/* Size of one Rela reloc */\n#define DT_STRSZ\t10\t\t/* Size of string table */\n#define DT_SYMENT\t11\t\t/* Size of one symbol table entry */\n#define DT_INIT\t\t12\t\t/* Address of init function */\n#define DT_FINI\t\t13\t\t/* Address of termination function */\n#define DT_SONAME\t14\t\t/* Name of shared object */\n#define DT_RPATH\t15\t\t/* Library search path (deprecated) */\n#define DT_SYMBOLIC\t16\t\t/* Start symbol search here */\n#define DT_REL\t\t17\t\t/* Address of Rel relocs */\n#define DT_RELSZ\t18\t\t/* Total size of Rel relocs */\n#define DT_RELENT\t19\t\t/* Size of one Rel reloc */\n#define DT_PLTREL\t20\t\t/* Type of reloc in PLT */\n#define DT_DEBUG\t21\t\t/* For debugging; unspecified */\n#define DT_TEXTREL\t22\t\t/* Reloc might modify .text */\n#define DT_JMPREL\t23\t\t/* Address of PLT relocs */\n#define\tDT_BIND_NOW\t24\t\t/* Process relocations of object */\n#define\tDT_INIT_ARRAY\t25\t\t/* Array with addresses of init fct */\n#define\tDT_FINI_ARRAY\t26\t\t/* Array with addresses of fini fct */\n#define\tDT_INIT_ARRAYSZ\t27\t\t/* Size in bytes of DT_INIT_ARRAY */\n#define\tDT_FINI_ARRAYSZ\t28\t\t/* Size in bytes of DT_FINI_ARRAY */\n#define DT_RUNPATH\t29\t\t/* Library search path */\n#define DT_FLAGS\t30\t\t/* Flags for the object being loaded */\n#define DT_ENCODING\t32\t\t/* Start of encoded range */\n#define DT_PREINIT_ARRAY 32\t\t/* Array with addresses of preinit fct*/\n#define DT_PREINIT_ARRAYSZ 33\t\t/* size in bytes of DT_PREINIT_ARRAY */\n#define\tDT_NUM\t\t34\t\t/* Number used */\n#define DT_LOOS\t\t0x6000000d\t/* Start of OS-specific */\n#define DT_HIOS\t\t0x6ffff000\t/* End of OS-specific */\n#define DT_LOPROC\t0x70000000\t/* Start of processor-specific */\n#define DT_HIPROC\t0x7fffffff\t/* End of processor-specific */\n#define\tDT_PROCNUM\tDT_MIPS_NUM\t/* Most used by any processor */\n\n/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the\n   Dyn.d_un.d_val field of the Elf*_Dyn structure.  This follows Sun's\n   approach.  */\n#define DT_VALRNGLO\t0x6ffffd00\n#define DT_GNU_PRELINKED 0x6ffffdf5\t/* Prelinking timestamp */\n#define DT_GNU_CONFLICTSZ 0x6ffffdf6\t/* Size of conflict section */\n#define DT_GNU_LIBLISTSZ 0x6ffffdf7\t/* Size of library list */\n#define DT_CHECKSUM\t0x6ffffdf8\n#define DT_PLTPADSZ\t0x6ffffdf9\n#define DT_MOVEENT\t0x6ffffdfa\n#define DT_MOVESZ\t0x6ffffdfb\n#define DT_FEATURE_1\t0x6ffffdfc\t/* Feature selection (DTF_*).  */\n#define DT_POSFLAG_1\t0x6ffffdfd\t/* Flags for DT_* entries, effecting\n\t\t\t\t\t   the following DT_* entry.  */\n#define DT_SYMINSZ\t0x6ffffdfe\t/* Size of syminfo table (in bytes) */\n#define DT_SYMINENT\t0x6ffffdff\t/* Entry size of syminfo */\n#define DT_VALRNGHI\t0x6ffffdff\n#define DT_VALTAGIDX(tag)\t(DT_VALRNGHI - (tag))\t/* Reverse order! */\n#define DT_VALNUM 12\n\n/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the\n   Dyn.d_un.d_ptr field of the Elf*_Dyn structure.\n\n   If any adjustment is made to the ELF object after it has been\n   built these entries will need to be adjusted.  */\n#define DT_ADDRRNGLO\t0x6ffffe00\n#define DT_GNU_HASH\t0x6ffffef5\t/* GNU-style hash table.  */\n#define DT_TLSDESC_PLT\t0x6ffffef6\n#define DT_TLSDESC_GOT\t0x6ffffef7\n#define DT_GNU_CONFLICT\t0x6ffffef8\t/* Start of conflict section */\n#define DT_GNU_LIBLIST\t0x6ffffef9\t/* Library list */\n#define DT_CONFIG\t0x6ffffefa\t/* Configuration information.  */\n#define DT_DEPAUDIT\t0x6ffffefb\t/* Dependency auditing.  */\n#define DT_AUDIT\t0x6ffffefc\t/* Object auditing.  */\n#define\tDT_PLTPAD\t0x6ffffefd\t/* PLT padding.  */\n#define\tDT_MOVETAB\t0x6ffffefe\t/* Move table.  */\n#define DT_SYMINFO\t0x6ffffeff\t/* Syminfo table.  */\n#define DT_ADDRRNGHI\t0x6ffffeff\n#define DT_ADDRTAGIDX(tag)\t(DT_ADDRRNGHI - (tag))\t/* Reverse order! */\n#define DT_ADDRNUM 11\n\n/* The versioning entry types.  The next are defined as part of the\n   GNU extension.  */\n#define DT_VERSYM\t0x6ffffff0\n\n#define DT_RELACOUNT\t0x6ffffff9\n#define DT_RELCOUNT\t0x6ffffffa\n\n/* These were chosen by Sun.  */\n#define DT_FLAGS_1\t0x6ffffffb\t/* State flags, see DF_1_* below.  */\n#define\tDT_VERDEF\t0x6ffffffc\t/* Address of version definition\n\t\t\t\t\t   table */\n#define\tDT_VERDEFNUM\t0x6ffffffd\t/* Number of version definitions */\n#define\tDT_VERNEED\t0x6ffffffe\t/* Address of table with needed\n\t\t\t\t\t   versions */\n#define\tDT_VERNEEDNUM\t0x6fffffff\t/* Number of needed versions */\n#define DT_VERSIONTAGIDX(tag)\t(DT_VERNEEDNUM - (tag))\t/* Reverse order! */\n#define DT_VERSIONTAGNUM 16\n\n/* Sun added these machine-independent extensions in the \"processor-specific\"\n   range.  Be compatible.  */\n#define DT_AUXILIARY    0x7ffffffd      /* Shared object to load before self */\n#define DT_FILTER       0x7fffffff      /* Shared object to get values from */\n#define DT_EXTRATAGIDX(tag)\t((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)\n#define DT_EXTRANUM\t3\n\n/* Values of `d_un.d_val' in the DT_FLAGS entry.  */\n#define DF_ORIGIN\t0x00000001\t/* Object may use DF_ORIGIN */\n#define DF_SYMBOLIC\t0x00000002\t/* Symbol resolutions starts here */\n#define DF_TEXTREL\t0x00000004\t/* Object contains text relocations */\n#define DF_BIND_NOW\t0x00000008\t/* No lazy binding for this object */\n#define DF_STATIC_TLS\t0x00000010\t/* Module uses the static TLS model */\n\n/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1\n   entry in the dynamic section.  */\n#define DF_1_NOW\t0x00000001\t/* Set RTLD_NOW for this object.  */\n#define DF_1_GLOBAL\t0x00000002\t/* Set RTLD_GLOBAL for this object.  */\n#define DF_1_GROUP\t0x00000004\t/* Set RTLD_GROUP for this object.  */\n#define DF_1_NODELETE\t0x00000008\t/* Set RTLD_NODELETE for this object.*/\n#define DF_1_LOADFLTR\t0x00000010\t/* Trigger filtee loading at runtime.*/\n#define DF_1_INITFIRST\t0x00000020\t/* Set RTLD_INITFIRST for this object*/\n#define DF_1_NOOPEN\t0x00000040\t/* Set RTLD_NOOPEN for this object.  */\n#define DF_1_ORIGIN\t0x00000080\t/* $ORIGIN must be handled.  */\n#define DF_1_DIRECT\t0x00000100\t/* Direct binding enabled.  */\n#define DF_1_TRANS\t0x00000200\n#define DF_1_INTERPOSE\t0x00000400\t/* Object is used to interpose.  */\n#define DF_1_NODEFLIB\t0x00000800\t/* Ignore default lib search path.  */\n#define DF_1_NODUMP\t0x00001000\t/* Object can't be dldump'ed.  */\n#define DF_1_CONFALT\t0x00002000\t/* Configuration alternative created.*/\n#define DF_1_ENDFILTEE\t0x00004000\t/* Filtee terminates filters search. */\n#define\tDF_1_DISPRELDNE\t0x00008000\t/* Disp reloc applied at build time. */\n#define\tDF_1_DISPRELPND\t0x00010000\t/* Disp reloc applied at run-time.  */\n\n/* Flags for the feature selection in DT_FEATURE_1.  */\n#define DTF_1_PARINIT\t0x00000001\n#define DTF_1_CONFEXP\t0x00000002\n\n/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry.  */\n#define DF_P1_LAZYLOAD\t0x00000001\t/* Lazyload following object.  */\n#define DF_P1_GROUPPERM\t0x00000002\t/* Symbols from next object are not\n\t\t\t\t\t   generally available.  */\n\n/* Version definition sections.  */\n\ntypedef struct\n{\n  Elf32_Half\tvd_version;\t\t/* Version revision */\n  Elf32_Half\tvd_flags;\t\t/* Version information */\n  Elf32_Half\tvd_ndx;\t\t\t/* Version Index */\n  Elf32_Half\tvd_cnt;\t\t\t/* Number of associated aux entries */\n  Elf32_Word\tvd_hash;\t\t/* Version name hash value */\n  Elf32_Word\tvd_aux;\t\t\t/* Offset in bytes to verdaux array */\n  Elf32_Word\tvd_next;\t\t/* Offset in bytes to next verdef\n\t\t\t\t\t   entry */\n} Elf32_Verdef;\n\ntypedef struct\n{\n  Elf64_Half\tvd_version;\t\t/* Version revision */\n  Elf64_Half\tvd_flags;\t\t/* Version information */\n  Elf64_Half\tvd_ndx;\t\t\t/* Version Index */\n  Elf64_Half\tvd_cnt;\t\t\t/* Number of associated aux entries */\n  Elf64_Word\tvd_hash;\t\t/* Version name hash value */\n  Elf64_Word\tvd_aux;\t\t\t/* Offset in bytes to verdaux array */\n  Elf64_Word\tvd_next;\t\t/* Offset in bytes to next verdef\n\t\t\t\t\t   entry */\n} Elf64_Verdef;\n\n\n/* Legal values for vd_version (version revision).  */\n#define VER_DEF_NONE\t0\t\t/* No version */\n#define VER_DEF_CURRENT\t1\t\t/* Current version */\n#define VER_DEF_NUM\t2\t\t/* Given version number */\n\n/* Legal values for vd_flags (version information flags).  */\n#define VER_FLG_BASE\t0x1\t\t/* Version definition of file itself */\n#define VER_FLG_WEAK\t0x2\t\t/* Weak version identifier */\n\n/* Versym symbol index values.  */\n#define\tVER_NDX_LOCAL\t\t0\t/* Symbol is local.  */\n#define\tVER_NDX_GLOBAL\t\t1\t/* Symbol is global.  */\n#define\tVER_NDX_LORESERVE\t0xff00\t/* Beginning of reserved entries.  */\n#define\tVER_NDX_ELIMINATE\t0xff01\t/* Symbol is to be eliminated.  */\n\n/* Auxialiary version information.  */\n\ntypedef struct\n{\n  Elf32_Word\tvda_name;\t\t/* Version or dependency names */\n  Elf32_Word\tvda_next;\t\t/* Offset in bytes to next verdaux\n\t\t\t\t\t   entry */\n} Elf32_Verdaux;\n\ntypedef struct\n{\n  Elf64_Word\tvda_name;\t\t/* Version or dependency names */\n  Elf64_Word\tvda_next;\t\t/* Offset in bytes to next verdaux\n\t\t\t\t\t   entry */\n} Elf64_Verdaux;\n\n\n/* Version dependency section.  */\n\ntypedef struct\n{\n  Elf32_Half\tvn_version;\t\t/* Version of structure */\n  Elf32_Half\tvn_cnt;\t\t\t/* Number of associated aux entries */\n  Elf32_Word\tvn_file;\t\t/* Offset of filename for this\n\t\t\t\t\t   dependency */\n  Elf32_Word\tvn_aux;\t\t\t/* Offset in bytes to vernaux array */\n  Elf32_Word\tvn_next;\t\t/* Offset in bytes to next verneed\n\t\t\t\t\t   entry */\n} Elf32_Verneed;\n\ntypedef struct\n{\n  Elf64_Half\tvn_version;\t\t/* Version of structure */\n  Elf64_Half\tvn_cnt;\t\t\t/* Number of associated aux entries */\n  Elf64_Word\tvn_file;\t\t/* Offset of filename for this\n\t\t\t\t\t   dependency */\n  Elf64_Word\tvn_aux;\t\t\t/* Offset in bytes to vernaux array */\n  Elf64_Word\tvn_next;\t\t/* Offset in bytes to next verneed\n\t\t\t\t\t   entry */\n} Elf64_Verneed;\n\n\n/* Legal values for vn_version (version revision).  */\n#define VER_NEED_NONE\t 0\t\t/* No version */\n#define VER_NEED_CURRENT 1\t\t/* Current version */\n#define VER_NEED_NUM\t 2\t\t/* Given version number */\n\n/* Auxiliary needed version information.  */\n\ntypedef struct\n{\n  Elf32_Word\tvna_hash;\t\t/* Hash value of dependency name */\n  Elf32_Half\tvna_flags;\t\t/* Dependency specific information */\n  Elf32_Half\tvna_other;\t\t/* Unused */\n  Elf32_Word\tvna_name;\t\t/* Dependency name string offset */\n  Elf32_Word\tvna_next;\t\t/* Offset in bytes to next vernaux\n\t\t\t\t\t   entry */\n} Elf32_Vernaux;\n\ntypedef struct\n{\n  Elf64_Word\tvna_hash;\t\t/* Hash value of dependency name */\n  Elf64_Half\tvna_flags;\t\t/* Dependency specific information */\n  Elf64_Half\tvna_other;\t\t/* Unused */\n  Elf64_Word\tvna_name;\t\t/* Dependency name string offset */\n  Elf64_Word\tvna_next;\t\t/* Offset in bytes to next vernaux\n\t\t\t\t\t   entry */\n} Elf64_Vernaux;\n\n\n/* Legal values for vna_flags.  */\n#define VER_FLG_WEAK\t0x2\t\t/* Weak version identifier */\n\n\n/* Auxiliary vector.  */\n\n/* This vector is normally only used by the program interpreter.  The\n   usual definition in an ABI supplement uses the name auxv_t.  The\n   vector is not usually defined in a standard <elf.h> file, but it\n   can't hurt.  We rename it to avoid conflicts.  The sizes of these\n   types are an arrangement between the exec server and the program\n   interpreter, so we don't fully specify them here.  */\n\ntypedef struct\n{\n  uint32_t a_type;\t\t/* Entry type */\n  union\n    {\n      uint32_t a_val;\t\t/* Integer value */\n      /* We use to have pointer elements added here.  We cannot do that,\n\t though, since it does not work when using 32-bit definitions\n\t on 64-bit platforms and vice versa.  */\n    } a_un;\n} Elf32_auxv_t;\n\ntypedef struct\n{\n  uint64_t a_type;\t\t/* Entry type */\n  union\n    {\n      uint64_t a_val;\t\t/* Integer value */\n      /* We use to have pointer elements added here.  We cannot do that,\n\t though, since it does not work when using 32-bit definitions\n\t on 64-bit platforms and vice versa.  */\n    } a_un;\n} Elf64_auxv_t;\n\n/* Legal values for a_type (entry type).  */\n\n#define AT_NULL\t\t0\t\t/* End of vector */\n#define AT_IGNORE\t1\t\t/* Entry should be ignored */\n#define AT_EXECFD\t2\t\t/* File descriptor of program */\n#define AT_PHDR\t\t3\t\t/* Program headers for program */\n#define AT_PHENT\t4\t\t/* Size of program header entry */\n#define AT_PHNUM\t5\t\t/* Number of program headers */\n#define AT_PAGESZ\t6\t\t/* System page size */\n#define AT_BASE\t\t7\t\t/* Base address of interpreter */\n#define AT_FLAGS\t8\t\t/* Flags */\n#define AT_ENTRY\t9\t\t/* Entry point of program */\n#define AT_NOTELF\t10\t\t/* Program is not ELF */\n#define AT_UID\t\t11\t\t/* Real uid */\n#define AT_EUID\t\t12\t\t/* Effective uid */\n#define AT_GID\t\t13\t\t/* Real gid */\n#define AT_EGID\t\t14\t\t/* Effective gid */\n#define AT_CLKTCK\t17\t\t/* Frequency of times() */\n\n/* Some more special a_type values describing the hardware.  */\n#define AT_PLATFORM\t15\t\t/* String identifying platform.  */\n#define AT_HWCAP\t16\t\t/* Machine dependent hints about\n\t\t\t\t\t   processor capabilities.  */\n\n/* This entry gives some information about the FPU initialization\n   performed by the kernel.  */\n#define AT_FPUCW\t18\t\t/* Used FPU control word.  */\n\n/* Cache block sizes.  */\n#define AT_DCACHEBSIZE\t19\t\t/* Data cache block size.  */\n#define AT_ICACHEBSIZE\t20\t\t/* Instruction cache block size.  */\n#define AT_UCACHEBSIZE\t21\t\t/* Unified cache block size.  */\n\n/* A special ignored value for PPC, used by the kernel to control the\n   interpretation of the AUXV. Must be > 16.  */\n#define AT_IGNOREPPC\t22\t\t/* Entry should be ignored.  */\n\n#define\tAT_SECURE\t23\t\t/* Boolean, was exec setuid-like?  */\n\n#define AT_BASE_PLATFORM 24\t\t/* String identifying real platforms.*/\n\n#define AT_RANDOM\t25\t\t/* Address of 16 random bytes.  */\n\n#define AT_EXECFN\t31\t\t/* Filename of executable.  */\n\n/* Pointer to the global system page used for system calls and other\n   nice things.  */\n#define AT_SYSINFO\t32\n#define AT_SYSINFO_EHDR\t33\n\n/* Shapes of the caches.  Bits 0-3 contains associativity; bits 4-7 contains\n   log2 of line size; mask those to get cache size.  */\n#define AT_L1I_CACHESHAPE\t34\n#define AT_L1D_CACHESHAPE\t35\n#define AT_L2_CACHESHAPE\t36\n#define AT_L3_CACHESHAPE\t37\n\n/* Note section contents.  Each entry in the note section begins with\n   a header of a fixed form.  */\n\ntypedef struct\n{\n  Elf32_Word n_namesz;\t\t\t/* Length of the note's name.  */\n  Elf32_Word n_descsz;\t\t\t/* Length of the note's descriptor.  */\n  Elf32_Word n_type;\t\t\t/* Type of the note.  */\n} Elf32_Nhdr;\n\ntypedef struct\n{\n  Elf64_Word n_namesz;\t\t\t/* Length of the note's name.  */\n  Elf64_Word n_descsz;\t\t\t/* Length of the note's descriptor.  */\n  Elf64_Word n_type;\t\t\t/* Type of the note.  */\n} Elf64_Nhdr;\n\n/* Known names of notes.  */\n\n/* Solaris entries in the note section have this name.  */\n#define ELF_NOTE_SOLARIS\t\"SUNW Solaris\"\n\n/* Note entries for GNU systems have this name.  */\n#define ELF_NOTE_GNU\t\t\"GNU\"\n\n\n/* Defined types of notes for Solaris.  */\n\n/* Value of descriptor (one word) is desired pagesize for the binary.  */\n#define ELF_NOTE_PAGESIZE_HINT\t1\n\n\n/* Defined note types for GNU systems.  */\n\n/* ABI information.  The descriptor consists of words:\n   word 0: OS descriptor\n   word 1: major version of the ABI\n   word 2: minor version of the ABI\n   word 3: subminor version of the ABI\n*/\n#define NT_GNU_ABI_TAG\t1\n#define ELF_NOTE_ABI\tNT_GNU_ABI_TAG /* Old name.  */\n\n/* Known OSes.  These values can appear in word 0 of an\n   NT_GNU_ABI_TAG note section entry.  */\n#define ELF_NOTE_OS_LINUX\t0\n#define ELF_NOTE_OS_GNU\t\t1\n#define ELF_NOTE_OS_SOLARIS2\t2\n#define ELF_NOTE_OS_FREEBSD\t3\n\n/* Synthetic hwcap information.  The descriptor begins with two words:\n   word 0: number of entries\n   word 1: bitmask of enabled entries\n   Then follow variable-length entries, one byte followed by a\n   '\\0'-terminated hwcap name string.  The byte gives the bit\n   number to test if enabled, (1U << bit) & bitmask.  */\n#define NT_GNU_HWCAP\t2\n\n/* Build ID bits as generated by ld --build-id.\n   The descriptor consists of any nonzero number of bytes.  */\n#define NT_GNU_BUILD_ID\t3\n\n/* Version note generated by GNU gold containing a version string.  */\n#define NT_GNU_GOLD_VERSION\t4\n\n\n/* Move records.  */\ntypedef struct\n{\n  Elf32_Xword m_value;\t\t/* Symbol value.  */\n  Elf32_Word m_info;\t\t/* Size and index.  */\n  Elf32_Word m_poffset;\t\t/* Symbol offset.  */\n  Elf32_Half m_repeat;\t\t/* Repeat count.  */\n  Elf32_Half m_stride;\t\t/* Stride info.  */\n} Elf32_Move;\n\ntypedef struct\n{\n  Elf64_Xword m_value;\t\t/* Symbol value.  */\n  Elf64_Xword m_info;\t\t/* Size and index.  */\n  Elf64_Xword m_poffset;\t/* Symbol offset.  */\n  Elf64_Half m_repeat;\t\t/* Repeat count.  */\n  Elf64_Half m_stride;\t\t/* Stride info.  */\n} Elf64_Move;\n\n/* Macro to construct move records.  */\n#define ELF32_M_SYM(info)\t((info) >> 8)\n#define ELF32_M_SIZE(info)\t((unsigned char) (info))\n#define ELF32_M_INFO(sym, size)\t(((sym) << 8) + (unsigned char) (size))\n\n#define ELF64_M_SYM(info)\tELF32_M_SYM (info)\n#define ELF64_M_SIZE(info)\tELF32_M_SIZE (info)\n#define ELF64_M_INFO(sym, size)\tELF32_M_INFO (sym, size)\n\n\n/* Motorola 68k specific definitions.  */\n\n/* Values for Elf32_Ehdr.e_flags.  */\n#define EF_CPU32\t0x00810000\n\n/* m68k relocs.  */\n\n#define R_68K_NONE\t0\t\t/* No reloc */\n#define R_68K_32\t1\t\t/* Direct 32 bit  */\n#define R_68K_16\t2\t\t/* Direct 16 bit  */\n#define R_68K_8\t\t3\t\t/* Direct 8 bit  */\n#define R_68K_PC32\t4\t\t/* PC relative 32 bit */\n#define R_68K_PC16\t5\t\t/* PC relative 16 bit */\n#define R_68K_PC8\t6\t\t/* PC relative 8 bit */\n#define R_68K_GOT32\t7\t\t/* 32 bit PC relative GOT entry */\n#define R_68K_GOT16\t8\t\t/* 16 bit PC relative GOT entry */\n#define R_68K_GOT8\t9\t\t/* 8 bit PC relative GOT entry */\n#define R_68K_GOT32O\t10\t\t/* 32 bit GOT offset */\n#define R_68K_GOT16O\t11\t\t/* 16 bit GOT offset */\n#define R_68K_GOT8O\t12\t\t/* 8 bit GOT offset */\n#define R_68K_PLT32\t13\t\t/* 32 bit PC relative PLT address */\n#define R_68K_PLT16\t14\t\t/* 16 bit PC relative PLT address */\n#define R_68K_PLT8\t15\t\t/* 8 bit PC relative PLT address */\n#define R_68K_PLT32O\t16\t\t/* 32 bit PLT offset */\n#define R_68K_PLT16O\t17\t\t/* 16 bit PLT offset */\n#define R_68K_PLT8O\t18\t\t/* 8 bit PLT offset */\n#define R_68K_COPY\t19\t\t/* Copy symbol at runtime */\n#define R_68K_GLOB_DAT\t20\t\t/* Create GOT entry */\n#define R_68K_JMP_SLOT\t21\t\t/* Create PLT entry */\n#define R_68K_RELATIVE\t22\t\t/* Adjust by program base */\n#define R_68K_TLS_GD32      25          /* 32 bit GOT offset for GD */\n#define R_68K_TLS_GD16      26          /* 16 bit GOT offset for GD */\n#define R_68K_TLS_GD8       27          /* 8 bit GOT offset for GD */\n#define R_68K_TLS_LDM32     28          /* 32 bit GOT offset for LDM */\n#define R_68K_TLS_LDM16     29          /* 16 bit GOT offset for LDM */\n#define R_68K_TLS_LDM8      30          /* 8 bit GOT offset for LDM */\n#define R_68K_TLS_LDO32     31          /* 32 bit module-relative offset */\n#define R_68K_TLS_LDO16     32          /* 16 bit module-relative offset */\n#define R_68K_TLS_LDO8      33          /* 8 bit module-relative offset */\n#define R_68K_TLS_IE32      34          /* 32 bit GOT offset for IE */\n#define R_68K_TLS_IE16      35          /* 16 bit GOT offset for IE */\n#define R_68K_TLS_IE8       36          /* 8 bit GOT offset for IE */\n#define R_68K_TLS_LE32      37          /* 32 bit offset relative to\n\t\t\t\t\t   static TLS block */\n#define R_68K_TLS_LE16      38          /* 16 bit offset relative to\n\t\t\t\t\t   static TLS block */\n#define R_68K_TLS_LE8       39          /* 8 bit offset relative to\n\t\t\t\t\t   static TLS block */\n#define R_68K_TLS_DTPMOD32  40          /* 32 bit module number */\n#define R_68K_TLS_DTPREL32  41          /* 32 bit module-relative offset */\n#define R_68K_TLS_TPREL32   42          /* 32 bit TP-relative offset */\n/* Keep this the last entry.  */\n#define R_68K_NUM\t43\n\n/* Intel 80386 specific definitions.  */\n\n/* i386 relocs.  */\n\n#define R_386_NONE\t   0\t\t/* No reloc */\n#define R_386_32\t   1\t\t/* Direct 32 bit  */\n#define R_386_PC32\t   2\t\t/* PC relative 32 bit */\n#define R_386_GOT32\t   3\t\t/* 32 bit GOT entry */\n#define R_386_PLT32\t   4\t\t/* 32 bit PLT address */\n#define R_386_COPY\t   5\t\t/* Copy symbol at runtime */\n#define R_386_GLOB_DAT\t   6\t\t/* Create GOT entry */\n#define R_386_JMP_SLOT\t   7\t\t/* Create PLT entry */\n#define R_386_RELATIVE\t   8\t\t/* Adjust by program base */\n#define R_386_GOTOFF\t   9\t\t/* 32 bit offset to GOT */\n#define R_386_GOTPC\t   10\t\t/* 32 bit PC relative offset to GOT */\n#define R_386_32PLT\t   11\n#define R_386_TLS_TPOFF\t   14\t\t/* Offset in static TLS block */\n#define R_386_TLS_IE\t   15\t\t/* Address of GOT entry for static TLS\n\t\t\t\t\t   block offset */\n#define R_386_TLS_GOTIE\t   16\t\t/* GOT entry for static TLS block\n\t\t\t\t\t   offset */\n#define R_386_TLS_LE\t   17\t\t/* Offset relative to static TLS\n\t\t\t\t\t   block */\n#define R_386_TLS_GD\t   18\t\t/* Direct 32 bit for GNU version of\n\t\t\t\t\t   general dynamic thread local data */\n#define R_386_TLS_LDM\t   19\t\t/* Direct 32 bit for GNU version of\n\t\t\t\t\t   local dynamic thread local data\n\t\t\t\t\t   in LE code */\n#define R_386_16\t   20\n#define R_386_PC16\t   21\n#define R_386_8\t\t   22\n#define R_386_PC8\t   23\n#define R_386_TLS_GD_32\t   24\t\t/* Direct 32 bit for general dynamic\n\t\t\t\t\t   thread local data */\n#define R_386_TLS_GD_PUSH  25\t\t/* Tag for pushl in GD TLS code */\n#define R_386_TLS_GD_CALL  26\t\t/* Relocation for call to\n\t\t\t\t\t   __tls_get_addr() */\n#define R_386_TLS_GD_POP   27\t\t/* Tag for popl in GD TLS code */\n#define R_386_TLS_LDM_32   28\t\t/* Direct 32 bit for local dynamic\n\t\t\t\t\t   thread local data in LE code */\n#define R_386_TLS_LDM_PUSH 29\t\t/* Tag for pushl in LDM TLS code */\n#define R_386_TLS_LDM_CALL 30\t\t/* Relocation for call to\n\t\t\t\t\t   __tls_get_addr() in LDM code */\n#define R_386_TLS_LDM_POP  31\t\t/* Tag for popl in LDM TLS code */\n#define R_386_TLS_LDO_32   32\t\t/* Offset relative to TLS block */\n#define R_386_TLS_IE_32\t   33\t\t/* GOT entry for negated static TLS\n\t\t\t\t\t   block offset */\n#define R_386_TLS_LE_32\t   34\t\t/* Negated offset relative to static\n\t\t\t\t\t   TLS block */\n#define R_386_TLS_DTPMOD32 35\t\t/* ID of module containing symbol */\n#define R_386_TLS_DTPOFF32 36\t\t/* Offset in TLS block */\n#define R_386_TLS_TPOFF32  37\t\t/* Negated offset in static TLS block */\n/* 38? */\n#define R_386_TLS_GOTDESC  39\t\t/* GOT offset for TLS descriptor.  */\n#define R_386_TLS_DESC_CALL 40\t\t/* Marker of call through TLS\n\t\t\t\t\t   descriptor for\n\t\t\t\t\t   relaxation.  */\n#define R_386_TLS_DESC     41\t\t/* TLS descriptor containing\n\t\t\t\t\t   pointer to code and to\n\t\t\t\t\t   argument, returning the TLS\n\t\t\t\t\t   offset for the symbol.  */\n#define R_386_IRELATIVE\t   42\t\t/* Adjust indirectly by program base */\n/* Keep this the last entry.  */\n#define R_386_NUM\t   43\n\n/* SUN SPARC specific definitions.  */\n\n/* Legal values for ST_TYPE subfield of st_info (symbol type).  */\n\n#define STT_SPARC_REGISTER\t13\t/* Global register reserved to app. */\n\n/* Values for Elf64_Ehdr.e_flags.  */\n\n#define EF_SPARCV9_MM\t\t3\n#define EF_SPARCV9_TSO\t\t0\n#define EF_SPARCV9_PSO\t\t1\n#define EF_SPARCV9_RMO\t\t2\n#define EF_SPARC_LEDATA\t\t0x800000 /* little endian data */\n#define EF_SPARC_EXT_MASK\t0xFFFF00\n#define EF_SPARC_32PLUS\t\t0x000100 /* generic V8+ features */\n#define EF_SPARC_SUN_US1\t0x000200 /* Sun UltraSPARC1 extensions */\n#define EF_SPARC_HAL_R1\t\t0x000400 /* HAL R1 extensions */\n#define EF_SPARC_SUN_US3\t0x000800 /* Sun UltraSPARCIII extensions */\n\n/* SPARC relocs.  */\n\n#define R_SPARC_NONE\t\t0\t/* No reloc */\n#define R_SPARC_8\t\t1\t/* Direct 8 bit */\n#define R_SPARC_16\t\t2\t/* Direct 16 bit */\n#define R_SPARC_32\t\t3\t/* Direct 32 bit */\n#define R_SPARC_DISP8\t\t4\t/* PC relative 8 bit */\n#define R_SPARC_DISP16\t\t5\t/* PC relative 16 bit */\n#define R_SPARC_DISP32\t\t6\t/* PC relative 32 bit */\n#define R_SPARC_WDISP30\t\t7\t/* PC relative 30 bit shifted */\n#define R_SPARC_WDISP22\t\t8\t/* PC relative 22 bit shifted */\n#define R_SPARC_HI22\t\t9\t/* High 22 bit */\n#define R_SPARC_22\t\t10\t/* Direct 22 bit */\n#define R_SPARC_13\t\t11\t/* Direct 13 bit */\n#define R_SPARC_LO10\t\t12\t/* Truncated 10 bit */\n#define R_SPARC_GOT10\t\t13\t/* Truncated 10 bit GOT entry */\n#define R_SPARC_GOT13\t\t14\t/* 13 bit GOT entry */\n#define R_SPARC_GOT22\t\t15\t/* 22 bit GOT entry shifted */\n#define R_SPARC_PC10\t\t16\t/* PC relative 10 bit truncated */\n#define R_SPARC_PC22\t\t17\t/* PC relative 22 bit shifted */\n#define R_SPARC_WPLT30\t\t18\t/* 30 bit PC relative PLT address */\n#define R_SPARC_COPY\t\t19\t/* Copy symbol at runtime */\n#define R_SPARC_GLOB_DAT\t20\t/* Create GOT entry */\n#define R_SPARC_JMP_SLOT\t21\t/* Create PLT entry */\n#define R_SPARC_RELATIVE\t22\t/* Adjust by program base */\n#define R_SPARC_UA32\t\t23\t/* Direct 32 bit unaligned */\n\n/* Additional Sparc64 relocs.  */\n\n#define R_SPARC_PLT32\t\t24\t/* Direct 32 bit ref to PLT entry */\n#define R_SPARC_HIPLT22\t\t25\t/* High 22 bit PLT entry */\n#define R_SPARC_LOPLT10\t\t26\t/* Truncated 10 bit PLT entry */\n#define R_SPARC_PCPLT32\t\t27\t/* PC rel 32 bit ref to PLT entry */\n#define R_SPARC_PCPLT22\t\t28\t/* PC rel high 22 bit PLT entry */\n#define R_SPARC_PCPLT10\t\t29\t/* PC rel trunc 10 bit PLT entry */\n#define R_SPARC_10\t\t30\t/* Direct 10 bit */\n#define R_SPARC_11\t\t31\t/* Direct 11 bit */\n#define R_SPARC_64\t\t32\t/* Direct 64 bit */\n#define R_SPARC_OLO10\t\t33\t/* 10bit with secondary 13bit addend */\n#define R_SPARC_HH22\t\t34\t/* Top 22 bits of direct 64 bit */\n#define R_SPARC_HM10\t\t35\t/* High middle 10 bits of ... */\n#define R_SPARC_LM22\t\t36\t/* Low middle 22 bits of ... */\n#define R_SPARC_PC_HH22\t\t37\t/* Top 22 bits of pc rel 64 bit */\n#define R_SPARC_PC_HM10\t\t38\t/* High middle 10 bit of ... */\n#define R_SPARC_PC_LM22\t\t39\t/* Low miggle 22 bits of ... */\n#define R_SPARC_WDISP16\t\t40\t/* PC relative 16 bit shifted */\n#define R_SPARC_WDISP19\t\t41\t/* PC relative 19 bit shifted */\n#define R_SPARC_GLOB_JMP\t42\t/* was part of v9 ABI but was removed */\n#define R_SPARC_7\t\t43\t/* Direct 7 bit */\n#define R_SPARC_5\t\t44\t/* Direct 5 bit */\n#define R_SPARC_6\t\t45\t/* Direct 6 bit */\n#define R_SPARC_DISP64\t\t46\t/* PC relative 64 bit */\n#define R_SPARC_PLT64\t\t47\t/* Direct 64 bit ref to PLT entry */\n#define R_SPARC_HIX22\t\t48\t/* High 22 bit complemented */\n#define R_SPARC_LOX10\t\t49\t/* Truncated 11 bit complemented */\n#define R_SPARC_H44\t\t50\t/* Direct high 12 of 44 bit */\n#define R_SPARC_M44\t\t51\t/* Direct mid 22 of 44 bit */\n#define R_SPARC_L44\t\t52\t/* Direct low 10 of 44 bit */\n#define R_SPARC_REGISTER\t53\t/* Global register usage */\n#define R_SPARC_UA64\t\t54\t/* Direct 64 bit unaligned */\n#define R_SPARC_UA16\t\t55\t/* Direct 16 bit unaligned */\n#define R_SPARC_TLS_GD_HI22\t56\n#define R_SPARC_TLS_GD_LO10\t57\n#define R_SPARC_TLS_GD_ADD\t58\n#define R_SPARC_TLS_GD_CALL\t59\n#define R_SPARC_TLS_LDM_HI22\t60\n#define R_SPARC_TLS_LDM_LO10\t61\n#define R_SPARC_TLS_LDM_ADD\t62\n#define R_SPARC_TLS_LDM_CALL\t63\n#define R_SPARC_TLS_LDO_HIX22\t64\n#define R_SPARC_TLS_LDO_LOX10\t65\n#define R_SPARC_TLS_LDO_ADD\t66\n#define R_SPARC_TLS_IE_HI22\t67\n#define R_SPARC_TLS_IE_LO10\t68\n#define R_SPARC_TLS_IE_LD\t69\n#define R_SPARC_TLS_IE_LDX\t70\n#define R_SPARC_TLS_IE_ADD\t71\n#define R_SPARC_TLS_LE_HIX22\t72\n#define R_SPARC_TLS_LE_LOX10\t73\n#define R_SPARC_TLS_DTPMOD32\t74\n#define R_SPARC_TLS_DTPMOD64\t75\n#define R_SPARC_TLS_DTPOFF32\t76\n#define R_SPARC_TLS_DTPOFF64\t77\n#define R_SPARC_TLS_TPOFF32\t78\n#define R_SPARC_TLS_TPOFF64\t79\n#define R_SPARC_GOTDATA_HIX22\t80\n#define R_SPARC_GOTDATA_LOX10\t81\n#define R_SPARC_GOTDATA_OP_HIX22\t82\n#define R_SPARC_GOTDATA_OP_LOX10\t83\n#define R_SPARC_GOTDATA_OP\t84\n#define R_SPARC_H34\t\t85\n#define R_SPARC_SIZE32\t\t86\n#define R_SPARC_SIZE64\t\t87\n#define R_SPARC_JMP_IREL\t248\n#define R_SPARC_IRELATIVE\t249\n#define R_SPARC_GNU_VTINHERIT\t250\n#define R_SPARC_GNU_VTENTRY\t251\n#define R_SPARC_REV32\t\t252\n/* Keep this the last entry.  */\n#define R_SPARC_NUM\t\t253\n\n/* For Sparc64, legal values for d_tag of Elf64_Dyn.  */\n\n#define DT_SPARC_REGISTER 0x70000001\n#define DT_SPARC_NUM\t2\n\n/* MIPS R3000 specific definitions.  */\n\n/* Legal values for e_flags field of Elf32_Ehdr.  */\n\n#define EF_MIPS_NOREORDER   1\t\t/* A .noreorder directive was used */\n#define EF_MIPS_PIC\t    2\t\t/* Contains PIC code */\n#define EF_MIPS_CPIC\t    4\t\t/* Uses PIC calling sequence */\n#define EF_MIPS_XGOT\t    8\n#define EF_MIPS_64BIT_WHIRL 16\n#define EF_MIPS_ABI2\t    32\n#define EF_MIPS_ABI_ON32    64\n#define EF_MIPS_ARCH\t    0xf0000000\t/* MIPS architecture level */\n\n/* Legal values for MIPS architecture level.  */\n\n#define EF_MIPS_ARCH_1\t    0x00000000\t/* -mips1 code.  */\n#define EF_MIPS_ARCH_2\t    0x10000000\t/* -mips2 code.  */\n#define EF_MIPS_ARCH_3\t    0x20000000\t/* -mips3 code.  */\n#define EF_MIPS_ARCH_4\t    0x30000000\t/* -mips4 code.  */\n#define EF_MIPS_ARCH_5\t    0x40000000\t/* -mips5 code.  */\n#define EF_MIPS_ARCH_32\t    0x60000000\t/* MIPS32 code.  */\n#define EF_MIPS_ARCH_64\t    0x70000000\t/* MIPS64 code.  */\n\n/* The following are non-official names and should not be used.  */\n\n#define E_MIPS_ARCH_1\t  0x00000000\t/* -mips1 code.  */\n#define E_MIPS_ARCH_2\t  0x10000000\t/* -mips2 code.  */\n#define E_MIPS_ARCH_3\t  0x20000000\t/* -mips3 code.  */\n#define E_MIPS_ARCH_4\t  0x30000000\t/* -mips4 code.  */\n#define E_MIPS_ARCH_5\t  0x40000000\t/* -mips5 code.  */\n#define E_MIPS_ARCH_32\t  0x60000000\t/* MIPS32 code.  */\n#define E_MIPS_ARCH_64\t  0x70000000\t/* MIPS64 code.  */\n\n/* Special section indices.  */\n\n#define SHN_MIPS_ACOMMON    0xff00\t/* Allocated common symbols */\n#define SHN_MIPS_TEXT\t    0xff01\t/* Allocated test symbols.  */\n#define SHN_MIPS_DATA\t    0xff02\t/* Allocated data symbols.  */\n#define SHN_MIPS_SCOMMON    0xff03\t/* Small common symbols */\n#define SHN_MIPS_SUNDEFINED 0xff04\t/* Small undefined symbols */\n\n/* Legal values for sh_type field of Elf32_Shdr.  */\n\n#define SHT_MIPS_LIBLIST       0x70000000 /* Shared objects used in link */\n#define SHT_MIPS_MSYM\t       0x70000001\n#define SHT_MIPS_CONFLICT      0x70000002 /* Conflicting symbols */\n#define SHT_MIPS_GPTAB\t       0x70000003 /* Global data area sizes */\n#define SHT_MIPS_UCODE\t       0x70000004 /* Reserved for SGI/MIPS compilers */\n#define SHT_MIPS_DEBUG\t       0x70000005 /* MIPS ECOFF debugging information*/\n#define SHT_MIPS_REGINFO       0x70000006 /* Register usage information */\n#define SHT_MIPS_PACKAGE       0x70000007\n#define SHT_MIPS_PACKSYM       0x70000008\n#define SHT_MIPS_RELD\t       0x70000009\n#define SHT_MIPS_IFACE         0x7000000b\n#define SHT_MIPS_CONTENT       0x7000000c\n#define SHT_MIPS_OPTIONS       0x7000000d /* Miscellaneous options.  */\n#define SHT_MIPS_SHDR\t       0x70000010\n#define SHT_MIPS_FDESC\t       0x70000011\n#define SHT_MIPS_EXTSYM\t       0x70000012\n#define SHT_MIPS_DENSE\t       0x70000013\n#define SHT_MIPS_PDESC\t       0x70000014\n#define SHT_MIPS_LOCSYM\t       0x70000015\n#define SHT_MIPS_AUXSYM\t       0x70000016\n#define SHT_MIPS_OPTSYM\t       0x70000017\n#define SHT_MIPS_LOCSTR\t       0x70000018\n#define SHT_MIPS_LINE\t       0x70000019\n#define SHT_MIPS_RFDESC\t       0x7000001a\n#define SHT_MIPS_DELTASYM      0x7000001b\n#define SHT_MIPS_DELTAINST     0x7000001c\n#define SHT_MIPS_DELTACLASS    0x7000001d\n#define SHT_MIPS_DWARF         0x7000001e /* DWARF debugging information.  */\n#define SHT_MIPS_DELTADECL     0x7000001f\n#define SHT_MIPS_SYMBOL_LIB    0x70000020\n#define SHT_MIPS_EVENTS\t       0x70000021 /* Event section.  */\n#define SHT_MIPS_TRANSLATE     0x70000022\n#define SHT_MIPS_PIXIE\t       0x70000023\n#define SHT_MIPS_XLATE\t       0x70000024\n#define SHT_MIPS_XLATE_DEBUG   0x70000025\n#define SHT_MIPS_WHIRL\t       0x70000026\n#define SHT_MIPS_EH_REGION     0x70000027\n#define SHT_MIPS_XLATE_OLD     0x70000028\n#define SHT_MIPS_PDR_EXCEPTION 0x70000029\n\n/* Legal values for sh_flags field of Elf32_Shdr.  */\n\n#define SHF_MIPS_GPREL\t 0x10000000\t/* Must be part of global data area */\n#define SHF_MIPS_MERGE\t 0x20000000\n#define SHF_MIPS_ADDR\t 0x40000000\n#define SHF_MIPS_STRINGS 0x80000000\n#define SHF_MIPS_NOSTRIP 0x08000000\n#define SHF_MIPS_LOCAL\t 0x04000000\n#define SHF_MIPS_NAMES\t 0x02000000\n#define SHF_MIPS_NODUPE\t 0x01000000\n\n\n/* Symbol tables.  */\n\n/* MIPS specific values for `st_other'.  */\n#define STO_MIPS_DEFAULT\t\t0x0\n#define STO_MIPS_INTERNAL\t\t0x1\n#define STO_MIPS_HIDDEN\t\t\t0x2\n#define STO_MIPS_PROTECTED\t\t0x3\n#define STO_MIPS_PLT\t\t\t0x8\n#define STO_MIPS_SC_ALIGN_UNUSED\t0xff\n\n/* MIPS specific values for `st_info'.  */\n#define STB_MIPS_SPLIT_COMMON\t\t13\n\n/* Entries found in sections of type SHT_MIPS_GPTAB.  */\n\ntypedef union\n{\n  struct\n    {\n      Elf32_Word gt_current_g_value;\t/* -G value used for compilation */\n      Elf32_Word gt_unused;\t\t/* Not used */\n    } gt_header;\t\t\t/* First entry in section */\n  struct\n    {\n      Elf32_Word gt_g_value;\t\t/* If this value were used for -G */\n      Elf32_Word gt_bytes;\t\t/* This many bytes would be used */\n    } gt_entry;\t\t\t\t/* Subsequent entries in section */\n} Elf32_gptab;\n\n/* Entry found in sections of type SHT_MIPS_REGINFO.  */\n\ntypedef struct\n{\n  Elf32_Word\tri_gprmask;\t\t/* General registers used */\n  Elf32_Word\tri_cprmask[4];\t\t/* Coprocessor registers used */\n  Elf32_Sword\tri_gp_value;\t\t/* $gp register value */\n} Elf32_RegInfo;\n\n/* Entries found in sections of type SHT_MIPS_OPTIONS.  */\n\ntypedef struct\n{\n  unsigned char kind;\t\t/* Determines interpretation of the\n\t\t\t\t   variable part of descriptor.  */\n  unsigned char size;\t\t/* Size of descriptor, including header.  */\n  Elf32_Section section;\t/* Section header index of section affected,\n\t\t\t\t   0 for global options.  */\n  Elf32_Word info;\t\t/* Kind-specific information.  */\n} Elf_Options;\n\n/* Values for `kind' field in Elf_Options.  */\n\n#define ODK_NULL\t0\t/* Undefined.  */\n#define ODK_REGINFO\t1\t/* Register usage information.  */\n#define ODK_EXCEPTIONS\t2\t/* Exception processing options.  */\n#define ODK_PAD\t\t3\t/* Section padding options.  */\n#define ODK_HWPATCH\t4\t/* Hardware workarounds performed */\n#define ODK_FILL\t5\t/* record the fill value used by the linker. */\n#define ODK_TAGS\t6\t/* reserve space for desktop tools to write. */\n#define ODK_HWAND\t7\t/* HW workarounds.  'AND' bits when merging. */\n#define ODK_HWOR\t8\t/* HW workarounds.  'OR' bits when merging.  */\n\n/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries.  */\n\n#define OEX_FPU_MIN\t0x1f\t/* FPE's which MUST be enabled.  */\n#define OEX_FPU_MAX\t0x1f00\t/* FPE's which MAY be enabled.  */\n#define OEX_PAGE0\t0x10000\t/* page zero must be mapped.  */\n#define OEX_SMM\t\t0x20000\t/* Force sequential memory mode?  */\n#define OEX_FPDBUG\t0x40000\t/* Force floating point debug mode?  */\n#define OEX_PRECISEFP\tOEX_FPDBUG\n#define OEX_DISMISS\t0x80000\t/* Dismiss invalid address faults?  */\n\n#define OEX_FPU_INVAL\t0x10\n#define OEX_FPU_DIV0\t0x08\n#define OEX_FPU_OFLO\t0x04\n#define OEX_FPU_UFLO\t0x02\n#define OEX_FPU_INEX\t0x01\n\n/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry.  */\n\n#define OHW_R4KEOP\t0x1\t/* R4000 end-of-page patch.  */\n#define OHW_R8KPFETCH\t0x2\t/* may need R8000 prefetch patch.  */\n#define OHW_R5KEOP\t0x4\t/* R5000 end-of-page patch.  */\n#define OHW_R5KCVTL\t0x8\t/* R5000 cvt.[ds].l bug.  clean=1.  */\n\n#define OPAD_PREFIX\t0x1\n#define OPAD_POSTFIX\t0x2\n#define OPAD_SYMBOL\t0x4\n\n/* Entry found in `.options' section.  */\n\ntypedef struct\n{\n  Elf32_Word hwp_flags1;\t/* Extra flags.  */\n  Elf32_Word hwp_flags2;\t/* Extra flags.  */\n} Elf_Options_Hw;\n\n/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries.  */\n\n#define OHWA0_R4KEOP_CHECKED\t0x00000001\n#define OHWA1_R4KEOP_CLEAN\t0x00000002\n\n/* MIPS relocs.  */\n\n#define R_MIPS_NONE\t\t0\t/* No reloc */\n#define R_MIPS_16\t\t1\t/* Direct 16 bit */\n#define R_MIPS_32\t\t2\t/* Direct 32 bit */\n#define R_MIPS_REL32\t\t3\t/* PC relative 32 bit */\n#define R_MIPS_26\t\t4\t/* Direct 26 bit shifted */\n#define R_MIPS_HI16\t\t5\t/* High 16 bit */\n#define R_MIPS_LO16\t\t6\t/* Low 16 bit */\n#define R_MIPS_GPREL16\t\t7\t/* GP relative 16 bit */\n#define R_MIPS_LITERAL\t\t8\t/* 16 bit literal entry */\n#define R_MIPS_GOT16\t\t9\t/* 16 bit GOT entry */\n#define R_MIPS_PC16\t\t10\t/* PC relative 16 bit */\n#define R_MIPS_CALL16\t\t11\t/* 16 bit GOT entry for function */\n#define R_MIPS_GPREL32\t\t12\t/* GP relative 32 bit */\n\n#define R_MIPS_SHIFT5\t\t16\n#define R_MIPS_SHIFT6\t\t17\n#define R_MIPS_64\t\t18\n#define R_MIPS_GOT_DISP\t\t19\n#define R_MIPS_GOT_PAGE\t\t20\n#define R_MIPS_GOT_OFST\t\t21\n#define R_MIPS_GOT_HI16\t\t22\n#define R_MIPS_GOT_LO16\t\t23\n#define R_MIPS_SUB\t\t24\n#define R_MIPS_INSERT_A\t\t25\n#define R_MIPS_INSERT_B\t\t26\n#define R_MIPS_DELETE\t\t27\n#define R_MIPS_HIGHER\t\t28\n#define R_MIPS_HIGHEST\t\t29\n#define R_MIPS_CALL_HI16\t30\n#define R_MIPS_CALL_LO16\t31\n#define R_MIPS_SCN_DISP\t\t32\n#define R_MIPS_REL16\t\t33\n#define R_MIPS_ADD_IMMEDIATE\t34\n#define R_MIPS_PJUMP\t\t35\n#define R_MIPS_RELGOT\t\t36\n#define R_MIPS_JALR\t\t37\n#define R_MIPS_TLS_DTPMOD32\t38\t/* Module number 32 bit */\n#define R_MIPS_TLS_DTPREL32\t39\t/* Module-relative offset 32 bit */\n#define R_MIPS_TLS_DTPMOD64\t40\t/* Module number 64 bit */\n#define R_MIPS_TLS_DTPREL64\t41\t/* Module-relative offset 64 bit */\n#define R_MIPS_TLS_GD\t\t42\t/* 16 bit GOT offset for GD */\n#define R_MIPS_TLS_LDM\t\t43\t/* 16 bit GOT offset for LDM */\n#define R_MIPS_TLS_DTPREL_HI16\t44\t/* Module-relative offset, high 16 bits */\n#define R_MIPS_TLS_DTPREL_LO16\t45\t/* Module-relative offset, low 16 bits */\n#define R_MIPS_TLS_GOTTPREL\t46\t/* 16 bit GOT offset for IE */\n#define R_MIPS_TLS_TPREL32\t47\t/* TP-relative offset, 32 bit */\n#define R_MIPS_TLS_TPREL64\t48\t/* TP-relative offset, 64 bit */\n#define R_MIPS_TLS_TPREL_HI16\t49\t/* TP-relative offset, high 16 bits */\n#define R_MIPS_TLS_TPREL_LO16\t50\t/* TP-relative offset, low 16 bits */\n#define R_MIPS_GLOB_DAT\t\t51\n#define R_MIPS_COPY\t\t126\n#define R_MIPS_JUMP_SLOT        127\n/* Keep this the last entry.  */\n#define R_MIPS_NUM\t\t128\n\n/* Legal values for p_type field of Elf32_Phdr.  */\n\n#define PT_MIPS_REGINFO\t0x70000000\t/* Register usage information */\n#define PT_MIPS_RTPROC  0x70000001\t/* Runtime procedure table. */\n#define PT_MIPS_OPTIONS 0x70000002\n\n/* Special program header types.  */\n\n#define PF_MIPS_LOCAL\t0x10000000\n\n/* Legal values for d_tag field of Elf32_Dyn.  */\n\n#define DT_MIPS_RLD_VERSION  0x70000001\t/* Runtime linker interface version */\n#define DT_MIPS_TIME_STAMP   0x70000002\t/* Timestamp */\n#define DT_MIPS_ICHECKSUM    0x70000003\t/* Checksum */\n#define DT_MIPS_IVERSION     0x70000004\t/* Version string (string tbl index) */\n#define DT_MIPS_FLAGS\t     0x70000005\t/* Flags */\n#define DT_MIPS_BASE_ADDRESS 0x70000006\t/* Base address */\n#define DT_MIPS_MSYM\t     0x70000007\n#define DT_MIPS_CONFLICT     0x70000008\t/* Address of CONFLICT section */\n#define DT_MIPS_LIBLIST\t     0x70000009\t/* Address of LIBLIST section */\n#define DT_MIPS_LOCAL_GOTNO  0x7000000a\t/* Number of local GOT entries */\n#define DT_MIPS_CONFLICTNO   0x7000000b\t/* Number of CONFLICT entries */\n#define DT_MIPS_LIBLISTNO    0x70000010\t/* Number of LIBLIST entries */\n#define DT_MIPS_SYMTABNO     0x70000011\t/* Number of DYNSYM entries */\n#define DT_MIPS_UNREFEXTNO   0x70000012\t/* First external DYNSYM */\n#define DT_MIPS_GOTSYM\t     0x70000013\t/* First GOT entry in DYNSYM */\n#define DT_MIPS_HIPAGENO     0x70000014\t/* Number of GOT page table entries */\n#define DT_MIPS_RLD_MAP\t     0x70000016\t/* Address of run time loader map.  */\n#define DT_MIPS_DELTA_CLASS  0x70000017\t/* Delta C++ class definition.  */\n#define DT_MIPS_DELTA_CLASS_NO    0x70000018 /* Number of entries in\n\t\t\t\t\t\tDT_MIPS_DELTA_CLASS.  */\n#define DT_MIPS_DELTA_INSTANCE    0x70000019 /* Delta C++ class instances.  */\n#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in\n\t\t\t\t\t\tDT_MIPS_DELTA_INSTANCE.  */\n#define DT_MIPS_DELTA_RELOC  0x7000001b /* Delta relocations.  */\n#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in\n\t\t\t\t\t     DT_MIPS_DELTA_RELOC.  */\n#define DT_MIPS_DELTA_SYM    0x7000001d /* Delta symbols that Delta\n\t\t\t\t\t   relocations refer to.  */\n#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in\n\t\t\t\t\t   DT_MIPS_DELTA_SYM.  */\n#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the\n\t\t\t\t\t     class declaration.  */\n#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in\n\t\t\t\t\t\tDT_MIPS_DELTA_CLASSSYM.  */\n#define DT_MIPS_CXX_FLAGS    0x70000022 /* Flags indicating for C++ flavor.  */\n#define DT_MIPS_PIXIE_INIT   0x70000023\n#define DT_MIPS_SYMBOL_LIB   0x70000024\n#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025\n#define DT_MIPS_LOCAL_GOTIDX 0x70000026\n#define DT_MIPS_HIDDEN_GOTIDX 0x70000027\n#define DT_MIPS_PROTECTED_GOTIDX 0x70000028\n#define DT_MIPS_OPTIONS\t     0x70000029 /* Address of .options.  */\n#define DT_MIPS_INTERFACE    0x7000002a /* Address of .interface.  */\n#define DT_MIPS_DYNSTR_ALIGN 0x7000002b\n#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */\n#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve\n\t\t\t\t\t\t    function stored in GOT.  */\n#define DT_MIPS_PERF_SUFFIX  0x7000002e /* Default suffix of dso to be added\n\t\t\t\t\t   by rld on dlopen() calls.  */\n#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */\n#define DT_MIPS_GP_VALUE     0x70000030 /* GP value for aux GOTs.  */\n#define DT_MIPS_AUX_DYNAMIC  0x70000031 /* Address of aux .dynamic.  */\n/* The address of .got.plt in an executable using the new non-PIC ABI.  */\n#define DT_MIPS_PLTGOT\t     0x70000032\n/* The base of the PLT in an executable using the new non-PIC ABI if that\n   PLT is writable.  For a non-writable PLT, this is omitted or has a zero\n   value.  */\n#define DT_MIPS_RWPLT        0x70000034\n#define DT_MIPS_NUM\t     0x35\n\n/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry.  */\n\n#define RHF_NONE\t\t   0\t\t/* No flags */\n#define RHF_QUICKSTART\t\t   (1 << 0)\t/* Use quickstart */\n#define RHF_NOTPOT\t\t   (1 << 1)\t/* Hash size not power of 2 */\n#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)\t/* Ignore LD_LIBRARY_PATH */\n#define RHF_NO_MOVE\t\t   (1 << 3)\n#define RHF_SGI_ONLY\t\t   (1 << 4)\n#define RHF_GUARANTEE_INIT\t   (1 << 5)\n#define RHF_DELTA_C_PLUS_PLUS\t   (1 << 6)\n#define RHF_GUARANTEE_START_INIT   (1 << 7)\n#define RHF_PIXIE\t\t   (1 << 8)\n#define RHF_DEFAULT_DELAY_LOAD\t   (1 << 9)\n#define RHF_REQUICKSTART\t   (1 << 10)\n#define RHF_REQUICKSTARTED\t   (1 << 11)\n#define RHF_CORD\t\t   (1 << 12)\n#define RHF_NO_UNRES_UNDEF\t   (1 << 13)\n#define RHF_RLD_ORDER_SAFE\t   (1 << 14)\n\n/* Entries found in sections of type SHT_MIPS_LIBLIST.  */\n\ntypedef struct\n{\n  Elf32_Word l_name;\t\t/* Name (string table index) */\n  Elf32_Word l_time_stamp;\t/* Timestamp */\n  Elf32_Word l_checksum;\t/* Checksum */\n  Elf32_Word l_version;\t\t/* Interface version */\n  Elf32_Word l_flags;\t\t/* Flags */\n} Elf32_Lib;\n\ntypedef struct\n{\n  Elf64_Word l_name;\t\t/* Name (string table index) */\n  Elf64_Word l_time_stamp;\t/* Timestamp */\n  Elf64_Word l_checksum;\t/* Checksum */\n  Elf64_Word l_version;\t\t/* Interface version */\n  Elf64_Word l_flags;\t\t/* Flags */\n} Elf64_Lib;\n\n\n/* Legal values for l_flags.  */\n\n#define LL_NONE\t\t  0\n#define LL_EXACT_MATCH\t  (1 << 0)\t/* Require exact match */\n#define LL_IGNORE_INT_VER (1 << 1)\t/* Ignore interface version */\n#define LL_REQUIRE_MINOR  (1 << 2)\n#define LL_EXPORTS\t  (1 << 3)\n#define LL_DELAY_LOAD\t  (1 << 4)\n#define LL_DELTA\t  (1 << 5)\n\n/* Entries found in sections of type SHT_MIPS_CONFLICT.  */\n\ntypedef Elf32_Addr Elf32_Conflict;\n\n\n/* HPPA specific definitions.  */\n\n/* Legal values for e_flags field of Elf32_Ehdr.  */\n\n#define EF_PARISC_TRAPNIL\t0x00010000 /* Trap nil pointer dereference.  */\n#define EF_PARISC_EXT\t\t0x00020000 /* Program uses arch. extensions. */\n#define EF_PARISC_LSB\t\t0x00040000 /* Program expects little endian. */\n#define EF_PARISC_WIDE\t\t0x00080000 /* Program expects wide mode.  */\n#define EF_PARISC_NO_KABP\t0x00100000 /* No kernel assisted branch\n\t\t\t\t\t      prediction.  */\n#define EF_PARISC_LAZYSWAP\t0x00400000 /* Allow lazy swapping.  */\n#define EF_PARISC_ARCH\t\t0x0000ffff /* Architecture version.  */\n\n/* Defined values for `e_flags & EF_PARISC_ARCH' are:  */\n\n#define EFA_PARISC_1_0\t\t    0x020b /* PA-RISC 1.0 big-endian.  */\n#define EFA_PARISC_1_1\t\t    0x0210 /* PA-RISC 1.1 big-endian.  */\n#define EFA_PARISC_2_0\t\t    0x0214 /* PA-RISC 2.0 big-endian.  */\n\n/* Additional section indeces.  */\n\n#define SHN_PARISC_ANSI_COMMON\t0xff00\t   /* Section for tenatively declared\n\t\t\t\t\t      symbols in ANSI C.  */\n#define SHN_PARISC_HUGE_COMMON\t0xff01\t   /* Common blocks in huge model.  */\n\n/* Legal values for sh_type field of Elf32_Shdr.  */\n\n#define SHT_PARISC_EXT\t\t0x70000000 /* Contains product specific ext. */\n#define SHT_PARISC_UNWIND\t0x70000001 /* Unwind information.  */\n#define SHT_PARISC_DOC\t\t0x70000002 /* Debug info for optimized code. */\n\n/* Legal values for sh_flags field of Elf32_Shdr.  */\n\n#define SHF_PARISC_SHORT\t0x20000000 /* Section with short addressing. */\n#define SHF_PARISC_HUGE\t\t0x40000000 /* Section far from gp.  */\n#define SHF_PARISC_SBP\t\t0x80000000 /* Static branch prediction code. */\n\n/* Legal values for ST_TYPE subfield of st_info (symbol type).  */\n\n#define STT_PARISC_MILLICODE\t13\t/* Millicode function entry point.  */\n\n#define STT_HP_OPAQUE\t\t(STT_LOOS + 0x1)\n#define STT_HP_STUB\t\t(STT_LOOS + 0x2)\n\n/* HPPA relocs.  */\n\n#define R_PARISC_NONE\t\t0\t/* No reloc.  */\n#define R_PARISC_DIR32\t\t1\t/* Direct 32-bit reference.  */\n#define R_PARISC_DIR21L\t\t2\t/* Left 21 bits of eff. address.  */\n#define R_PARISC_DIR17R\t\t3\t/* Right 17 bits of eff. address.  */\n#define R_PARISC_DIR17F\t\t4\t/* 17 bits of eff. address.  */\n#define R_PARISC_DIR14R\t\t6\t/* Right 14 bits of eff. address.  */\n#define R_PARISC_PCREL32\t9\t/* 32-bit rel. address.  */\n#define R_PARISC_PCREL21L\t10\t/* Left 21 bits of rel. address.  */\n#define R_PARISC_PCREL17R\t11\t/* Right 17 bits of rel. address.  */\n#define R_PARISC_PCREL17F\t12\t/* 17 bits of rel. address.  */\n#define R_PARISC_PCREL14R\t14\t/* Right 14 bits of rel. address.  */\n#define R_PARISC_DPREL21L\t18\t/* Left 21 bits of rel. address.  */\n#define R_PARISC_DPREL14R\t22\t/* Right 14 bits of rel. address.  */\n#define R_PARISC_GPREL21L\t26\t/* GP-relative, left 21 bits.  */\n#define R_PARISC_GPREL14R\t30\t/* GP-relative, right 14 bits.  */\n#define R_PARISC_LTOFF21L\t34\t/* LT-relative, left 21 bits.  */\n#define R_PARISC_LTOFF14R\t38\t/* LT-relative, right 14 bits.  */\n#define R_PARISC_SECREL32\t41\t/* 32 bits section rel. address.  */\n#define R_PARISC_SEGBASE\t48\t/* No relocation, set segment base.  */\n#define R_PARISC_SEGREL32\t49\t/* 32 bits segment rel. address.  */\n#define R_PARISC_PLTOFF21L\t50\t/* PLT rel. address, left 21 bits.  */\n#define R_PARISC_PLTOFF14R\t54\t/* PLT rel. address, right 14 bits.  */\n#define R_PARISC_LTOFF_FPTR32\t57\t/* 32 bits LT-rel. function pointer. */\n#define R_PARISC_LTOFF_FPTR21L\t58\t/* LT-rel. fct ptr, left 21 bits. */\n#define R_PARISC_LTOFF_FPTR14R\t62\t/* LT-rel. fct ptr, right 14 bits. */\n#define R_PARISC_FPTR64\t\t64\t/* 64 bits function address.  */\n#define R_PARISC_PLABEL32\t65\t/* 32 bits function address.  */\n#define R_PARISC_PLABEL21L\t66\t/* Left 21 bits of fdesc address.  */\n#define R_PARISC_PLABEL14R\t70\t/* Right 14 bits of fdesc address.  */\n#define R_PARISC_PCREL64\t72\t/* 64 bits PC-rel. address.  */\n#define R_PARISC_PCREL22F\t74\t/* 22 bits PC-rel. address.  */\n#define R_PARISC_PCREL14WR\t75\t/* PC-rel. address, right 14 bits.  */\n#define R_PARISC_PCREL14DR\t76\t/* PC rel. address, right 14 bits.  */\n#define R_PARISC_PCREL16F\t77\t/* 16 bits PC-rel. address.  */\n#define R_PARISC_PCREL16WF\t78\t/* 16 bits PC-rel. address.  */\n#define R_PARISC_PCREL16DF\t79\t/* 16 bits PC-rel. address.  */\n#define R_PARISC_DIR64\t\t80\t/* 64 bits of eff. address.  */\n#define R_PARISC_DIR14WR\t83\t/* 14 bits of eff. address.  */\n#define R_PARISC_DIR14DR\t84\t/* 14 bits of eff. address.  */\n#define R_PARISC_DIR16F\t\t85\t/* 16 bits of eff. address.  */\n#define R_PARISC_DIR16WF\t86\t/* 16 bits of eff. address.  */\n#define R_PARISC_DIR16DF\t87\t/* 16 bits of eff. address.  */\n#define R_PARISC_GPREL64\t88\t/* 64 bits of GP-rel. address.  */\n#define R_PARISC_GPREL14WR\t91\t/* GP-rel. address, right 14 bits.  */\n#define R_PARISC_GPREL14DR\t92\t/* GP-rel. address, right 14 bits.  */\n#define R_PARISC_GPREL16F\t93\t/* 16 bits GP-rel. address.  */\n#define R_PARISC_GPREL16WF\t94\t/* 16 bits GP-rel. address.  */\n#define R_PARISC_GPREL16DF\t95\t/* 16 bits GP-rel. address.  */\n#define R_PARISC_LTOFF64\t96\t/* 64 bits LT-rel. address.  */\n#define R_PARISC_LTOFF14WR\t99\t/* LT-rel. address, right 14 bits.  */\n#define R_PARISC_LTOFF14DR\t100\t/* LT-rel. address, right 14 bits.  */\n#define R_PARISC_LTOFF16F\t101\t/* 16 bits LT-rel. address.  */\n#define R_PARISC_LTOFF16WF\t102\t/* 16 bits LT-rel. address.  */\n#define R_PARISC_LTOFF16DF\t103\t/* 16 bits LT-rel. address.  */\n#define R_PARISC_SECREL64\t104\t/* 64 bits section rel. address.  */\n#define R_PARISC_SEGREL64\t112\t/* 64 bits segment rel. address.  */\n#define R_PARISC_PLTOFF14WR\t115\t/* PLT-rel. address, right 14 bits.  */\n#define R_PARISC_PLTOFF14DR\t116\t/* PLT-rel. address, right 14 bits.  */\n#define R_PARISC_PLTOFF16F\t117\t/* 16 bits LT-rel. address.  */\n#define R_PARISC_PLTOFF16WF\t118\t/* 16 bits PLT-rel. address.  */\n#define R_PARISC_PLTOFF16DF\t119\t/* 16 bits PLT-rel. address.  */\n#define R_PARISC_LTOFF_FPTR64\t120\t/* 64 bits LT-rel. function ptr.  */\n#define R_PARISC_LTOFF_FPTR14WR\t123\t/* LT-rel. fct. ptr., right 14 bits. */\n#define R_PARISC_LTOFF_FPTR14DR\t124\t/* LT-rel. fct. ptr., right 14 bits. */\n#define R_PARISC_LTOFF_FPTR16F\t125\t/* 16 bits LT-rel. function ptr.  */\n#define R_PARISC_LTOFF_FPTR16WF\t126\t/* 16 bits LT-rel. function ptr.  */\n#define R_PARISC_LTOFF_FPTR16DF\t127\t/* 16 bits LT-rel. function ptr.  */\n#define R_PARISC_LORESERVE\t128\n#define R_PARISC_COPY\t\t128\t/* Copy relocation.  */\n#define R_PARISC_IPLT\t\t129\t/* Dynamic reloc, imported PLT */\n#define R_PARISC_EPLT\t\t130\t/* Dynamic reloc, exported PLT */\n#define R_PARISC_TPREL32\t153\t/* 32 bits TP-rel. address.  */\n#define R_PARISC_TPREL21L\t154\t/* TP-rel. address, left 21 bits.  */\n#define R_PARISC_TPREL14R\t158\t/* TP-rel. address, right 14 bits.  */\n#define R_PARISC_LTOFF_TP21L\t162\t/* LT-TP-rel. address, left 21 bits. */\n#define R_PARISC_LTOFF_TP14R\t166\t/* LT-TP-rel. address, right 14 bits.*/\n#define R_PARISC_LTOFF_TP14F\t167\t/* 14 bits LT-TP-rel. address.  */\n#define R_PARISC_TPREL64\t216\t/* 64 bits TP-rel. address.  */\n#define R_PARISC_TPREL14WR\t219\t/* TP-rel. address, right 14 bits.  */\n#define R_PARISC_TPREL14DR\t220\t/* TP-rel. address, right 14 bits.  */\n#define R_PARISC_TPREL16F\t221\t/* 16 bits TP-rel. address.  */\n#define R_PARISC_TPREL16WF\t222\t/* 16 bits TP-rel. address.  */\n#define R_PARISC_TPREL16DF\t223\t/* 16 bits TP-rel. address.  */\n#define R_PARISC_LTOFF_TP64\t224\t/* 64 bits LT-TP-rel. address.  */\n#define R_PARISC_LTOFF_TP14WR\t227\t/* LT-TP-rel. address, right 14 bits.*/\n#define R_PARISC_LTOFF_TP14DR\t228\t/* LT-TP-rel. address, right 14 bits.*/\n#define R_PARISC_LTOFF_TP16F\t229\t/* 16 bits LT-TP-rel. address.  */\n#define R_PARISC_LTOFF_TP16WF\t230\t/* 16 bits LT-TP-rel. address.  */\n#define R_PARISC_LTOFF_TP16DF\t231\t/* 16 bits LT-TP-rel. address.  */\n#define R_PARISC_GNU_VTENTRY\t232\n#define R_PARISC_GNU_VTINHERIT\t233\n#define R_PARISC_TLS_GD21L\t234\t/* GD 21-bit left.  */\n#define R_PARISC_TLS_GD14R\t235\t/* GD 14-bit right.  */\n#define R_PARISC_TLS_GDCALL\t236\t/* GD call to __t_g_a.  */\n#define R_PARISC_TLS_LDM21L\t237\t/* LD module 21-bit left.  */\n#define R_PARISC_TLS_LDM14R\t238\t/* LD module 14-bit right.  */\n#define R_PARISC_TLS_LDMCALL\t239\t/* LD module call to __t_g_a.  */\n#define R_PARISC_TLS_LDO21L\t240\t/* LD offset 21-bit left.  */\n#define R_PARISC_TLS_LDO14R\t241\t/* LD offset 14-bit right.  */\n#define R_PARISC_TLS_DTPMOD32\t242\t/* DTP module 32-bit.  */\n#define R_PARISC_TLS_DTPMOD64\t243\t/* DTP module 64-bit.  */\n#define R_PARISC_TLS_DTPOFF32\t244\t/* DTP offset 32-bit.  */\n#define R_PARISC_TLS_DTPOFF64\t245\t/* DTP offset 32-bit.  */\n#define R_PARISC_TLS_LE21L\tR_PARISC_TPREL21L\n#define R_PARISC_TLS_LE14R\tR_PARISC_TPREL14R\n#define R_PARISC_TLS_IE21L\tR_PARISC_LTOFF_TP21L\n#define R_PARISC_TLS_IE14R\tR_PARISC_LTOFF_TP14R\n#define R_PARISC_TLS_TPREL32\tR_PARISC_TPREL32\n#define R_PARISC_TLS_TPREL64\tR_PARISC_TPREL64\n#define R_PARISC_HIRESERVE\t255\n\n/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr.  */\n\n#define PT_HP_TLS\t\t(PT_LOOS + 0x0)\n#define PT_HP_CORE_NONE\t\t(PT_LOOS + 0x1)\n#define PT_HP_CORE_VERSION\t(PT_LOOS + 0x2)\n#define PT_HP_CORE_KERNEL\t(PT_LOOS + 0x3)\n#define PT_HP_CORE_COMM\t\t(PT_LOOS + 0x4)\n#define PT_HP_CORE_PROC\t\t(PT_LOOS + 0x5)\n#define PT_HP_CORE_LOADABLE\t(PT_LOOS + 0x6)\n#define PT_HP_CORE_STACK\t(PT_LOOS + 0x7)\n#define PT_HP_CORE_SHM\t\t(PT_LOOS + 0x8)\n#define PT_HP_CORE_MMF\t\t(PT_LOOS + 0x9)\n#define PT_HP_PARALLEL\t\t(PT_LOOS + 0x10)\n#define PT_HP_FASTBIND\t\t(PT_LOOS + 0x11)\n#define PT_HP_OPT_ANNOT\t\t(PT_LOOS + 0x12)\n#define PT_HP_HSL_ANNOT\t\t(PT_LOOS + 0x13)\n#define PT_HP_STACK\t\t(PT_LOOS + 0x14)\n\n#define PT_PARISC_ARCHEXT\t0x70000000\n#define PT_PARISC_UNWIND\t0x70000001\n\n/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr.  */\n\n#define PF_PARISC_SBP\t\t0x08000000\n\n#define PF_HP_PAGE_SIZE\t\t0x00100000\n#define PF_HP_FAR_SHARED\t0x00200000\n#define PF_HP_NEAR_SHARED\t0x00400000\n#define PF_HP_CODE\t\t0x01000000\n#define PF_HP_MODIFY\t\t0x02000000\n#define PF_HP_LAZYSWAP\t\t0x04000000\n#define PF_HP_SBP\t\t0x08000000\n\n\n/* Alpha specific definitions.  */\n\n/* Legal values for e_flags field of Elf64_Ehdr.  */\n\n#define EF_ALPHA_32BIT\t\t1\t/* All addresses must be < 2GB.  */\n#define EF_ALPHA_CANRELAX\t2\t/* Relocations for relaxing exist.  */\n\n/* Legal values for sh_type field of Elf64_Shdr.  */\n\n/* These two are primerily concerned with ECOFF debugging info.  */\n#define SHT_ALPHA_DEBUG\t\t0x70000001\n#define SHT_ALPHA_REGINFO\t0x70000002\n\n/* Legal values for sh_flags field of Elf64_Shdr.  */\n\n#define SHF_ALPHA_GPREL\t\t0x10000000\n\n/* Legal values for st_other field of Elf64_Sym.  */\n#define STO_ALPHA_NOPV\t\t0x80\t/* No PV required.  */\n#define STO_ALPHA_STD_GPLOAD\t0x88\t/* PV only used for initial ldgp.  */\n\n/* Alpha relocs.  */\n\n#define R_ALPHA_NONE\t\t0\t/* No reloc */\n#define R_ALPHA_REFLONG\t\t1\t/* Direct 32 bit */\n#define R_ALPHA_REFQUAD\t\t2\t/* Direct 64 bit */\n#define R_ALPHA_GPREL32\t\t3\t/* GP relative 32 bit */\n#define R_ALPHA_LITERAL\t\t4\t/* GP relative 16 bit w/optimization */\n#define R_ALPHA_LITUSE\t\t5\t/* Optimization hint for LITERAL */\n#define R_ALPHA_GPDISP\t\t6\t/* Add displacement to GP */\n#define R_ALPHA_BRADDR\t\t7\t/* PC+4 relative 23 bit shifted */\n#define R_ALPHA_HINT\t\t8\t/* PC+4 relative 16 bit shifted */\n#define R_ALPHA_SREL16\t\t9\t/* PC relative 16 bit */\n#define R_ALPHA_SREL32\t\t10\t/* PC relative 32 bit */\n#define R_ALPHA_SREL64\t\t11\t/* PC relative 64 bit */\n#define R_ALPHA_GPRELHIGH\t17\t/* GP relative 32 bit, high 16 bits */\n#define R_ALPHA_GPRELLOW\t18\t/* GP relative 32 bit, low 16 bits */\n#define R_ALPHA_GPREL16\t\t19\t/* GP relative 16 bit */\n#define R_ALPHA_COPY\t\t24\t/* Copy symbol at runtime */\n#define R_ALPHA_GLOB_DAT\t25\t/* Create GOT entry */\n#define R_ALPHA_JMP_SLOT\t26\t/* Create PLT entry */\n#define R_ALPHA_RELATIVE\t27\t/* Adjust by program base */\n#define R_ALPHA_TLS_GD_HI\t28\n#define R_ALPHA_TLSGD\t\t29\n#define R_ALPHA_TLS_LDM\t\t30\n#define R_ALPHA_DTPMOD64\t31\n#define R_ALPHA_GOTDTPREL\t32\n#define R_ALPHA_DTPREL64\t33\n#define R_ALPHA_DTPRELHI\t34\n#define R_ALPHA_DTPRELLO\t35\n#define R_ALPHA_DTPREL16\t36\n#define R_ALPHA_GOTTPREL\t37\n#define R_ALPHA_TPREL64\t\t38\n#define R_ALPHA_TPRELHI\t\t39\n#define R_ALPHA_TPRELLO\t\t40\n#define R_ALPHA_TPREL16\t\t41\n/* Keep this the last entry.  */\n#define R_ALPHA_NUM\t\t46\n\n/* Magic values of the LITUSE relocation addend.  */\n#define LITUSE_ALPHA_ADDR\t0\n#define LITUSE_ALPHA_BASE\t1\n#define LITUSE_ALPHA_BYTOFF\t2\n#define LITUSE_ALPHA_JSR\t3\n#define LITUSE_ALPHA_TLS_GD\t4\n#define LITUSE_ALPHA_TLS_LDM\t5\n\n/* Legal values for d_tag of Elf64_Dyn.  */\n#define DT_ALPHA_PLTRO\t\t(DT_LOPROC + 0)\n#define DT_ALPHA_NUM\t\t1\n\n/* PowerPC specific declarations */\n\n/* Values for Elf32/64_Ehdr.e_flags.  */\n#define EF_PPC_EMB\t\t0x80000000\t/* PowerPC embedded flag */\n\n/* Cygnus local bits below */\n#define EF_PPC_RELOCATABLE\t0x00010000\t/* PowerPC -mrelocatable flag*/\n#define EF_PPC_RELOCATABLE_LIB\t0x00008000\t/* PowerPC -mrelocatable-lib\n\t\t\t\t\t\t   flag */\n\n/* PowerPC relocations defined by the ABIs */\n#define R_PPC_NONE\t\t0\n#define R_PPC_ADDR32\t\t1\t/* 32bit absolute address */\n#define R_PPC_ADDR24\t\t2\t/* 26bit address, 2 bits ignored.  */\n#define R_PPC_ADDR16\t\t3\t/* 16bit absolute address */\n#define R_PPC_ADDR16_LO\t\t4\t/* lower 16bit of absolute address */\n#define R_PPC_ADDR16_HI\t\t5\t/* high 16bit of absolute address */\n#define R_PPC_ADDR16_HA\t\t6\t/* adjusted high 16bit */\n#define R_PPC_ADDR14\t\t7\t/* 16bit address, 2 bits ignored */\n#define R_PPC_ADDR14_BRTAKEN\t8\n#define R_PPC_ADDR14_BRNTAKEN\t9\n#define R_PPC_REL24\t\t10\t/* PC relative 26 bit */\n#define R_PPC_REL14\t\t11\t/* PC relative 16 bit */\n#define R_PPC_REL14_BRTAKEN\t12\n#define R_PPC_REL14_BRNTAKEN\t13\n#define R_PPC_GOT16\t\t14\n#define R_PPC_GOT16_LO\t\t15\n#define R_PPC_GOT16_HI\t\t16\n#define R_PPC_GOT16_HA\t\t17\n#define R_PPC_PLTREL24\t\t18\n#define R_PPC_COPY\t\t19\n#define R_PPC_GLOB_DAT\t\t20\n#define R_PPC_JMP_SLOT\t\t21\n#define R_PPC_RELATIVE\t\t22\n#define R_PPC_LOCAL24PC\t\t23\n#define R_PPC_UADDR32\t\t24\n#define R_PPC_UADDR16\t\t25\n#define R_PPC_REL32\t\t26\n#define R_PPC_PLT32\t\t27\n#define R_PPC_PLTREL32\t\t28\n#define R_PPC_PLT16_LO\t\t29\n#define R_PPC_PLT16_HI\t\t30\n#define R_PPC_PLT16_HA\t\t31\n#define R_PPC_SDAREL16\t\t32\n#define R_PPC_SECTOFF\t\t33\n#define R_PPC_SECTOFF_LO\t34\n#define R_PPC_SECTOFF_HI\t35\n#define R_PPC_SECTOFF_HA\t36\n\n/* PowerPC relocations defined for the TLS access ABI.  */\n#define R_PPC_TLS\t\t67 /* none\t(sym+add)@tls */\n#define R_PPC_DTPMOD32\t\t68 /* word32\t(sym+add)@dtpmod */\n#define R_PPC_TPREL16\t\t69 /* half16*\t(sym+add)@tprel */\n#define R_PPC_TPREL16_LO\t70 /* half16\t(sym+add)@tprel@l */\n#define R_PPC_TPREL16_HI\t71 /* half16\t(sym+add)@tprel@h */\n#define R_PPC_TPREL16_HA\t72 /* half16\t(sym+add)@tprel@ha */\n#define R_PPC_TPREL32\t\t73 /* word32\t(sym+add)@tprel */\n#define R_PPC_DTPREL16\t\t74 /* half16*\t(sym+add)@dtprel */\n#define R_PPC_DTPREL16_LO\t75 /* half16\t(sym+add)@dtprel@l */\n#define R_PPC_DTPREL16_HI\t76 /* half16\t(sym+add)@dtprel@h */\n#define R_PPC_DTPREL16_HA\t77 /* half16\t(sym+add)@dtprel@ha */\n#define R_PPC_DTPREL32\t\t78 /* word32\t(sym+add)@dtprel */\n#define R_PPC_GOT_TLSGD16\t79 /* half16*\t(sym+add)@got@tlsgd */\n#define R_PPC_GOT_TLSGD16_LO\t80 /* half16\t(sym+add)@got@tlsgd@l */\n#define R_PPC_GOT_TLSGD16_HI\t81 /* half16\t(sym+add)@got@tlsgd@h */\n#define R_PPC_GOT_TLSGD16_HA\t82 /* half16\t(sym+add)@got@tlsgd@ha */\n#define R_PPC_GOT_TLSLD16\t83 /* half16*\t(sym+add)@got@tlsld */\n#define R_PPC_GOT_TLSLD16_LO\t84 /* half16\t(sym+add)@got@tlsld@l */\n#define R_PPC_GOT_TLSLD16_HI\t85 /* half16\t(sym+add)@got@tlsld@h */\n#define R_PPC_GOT_TLSLD16_HA\t86 /* half16\t(sym+add)@got@tlsld@ha */\n#define R_PPC_GOT_TPREL16\t87 /* half16*\t(sym+add)@got@tprel */\n#define R_PPC_GOT_TPREL16_LO\t88 /* half16\t(sym+add)@got@tprel@l */\n#define R_PPC_GOT_TPREL16_HI\t89 /* half16\t(sym+add)@got@tprel@h */\n#define R_PPC_GOT_TPREL16_HA\t90 /* half16\t(sym+add)@got@tprel@ha */\n#define R_PPC_GOT_DTPREL16\t91 /* half16*\t(sym+add)@got@dtprel */\n#define R_PPC_GOT_DTPREL16_LO\t92 /* half16*\t(sym+add)@got@dtprel@l */\n#define R_PPC_GOT_DTPREL16_HI\t93 /* half16*\t(sym+add)@got@dtprel@h */\n#define R_PPC_GOT_DTPREL16_HA\t94 /* half16*\t(sym+add)@got@dtprel@ha */\n\n/* The remaining relocs are from the Embedded ELF ABI, and are not\n   in the SVR4 ELF ABI.  */\n#define R_PPC_EMB_NADDR32\t101\n#define R_PPC_EMB_NADDR16\t102\n#define R_PPC_EMB_NADDR16_LO\t103\n#define R_PPC_EMB_NADDR16_HI\t104\n#define R_PPC_EMB_NADDR16_HA\t105\n#define R_PPC_EMB_SDAI16\t106\n#define R_PPC_EMB_SDA2I16\t107\n#define R_PPC_EMB_SDA2REL\t108\n#define R_PPC_EMB_SDA21\t\t109\t/* 16 bit offset in SDA */\n#define R_PPC_EMB_MRKREF\t110\n#define R_PPC_EMB_RELSEC16\t111\n#define R_PPC_EMB_RELST_LO\t112\n#define R_PPC_EMB_RELST_HI\t113\n#define R_PPC_EMB_RELST_HA\t114\n#define R_PPC_EMB_BIT_FLD\t115\n#define R_PPC_EMB_RELSDA\t116\t/* 16 bit relative offset in SDA */\n\n/* Diab tool relocations.  */\n#define R_PPC_DIAB_SDA21_LO\t180\t/* like EMB_SDA21, but lower 16 bit */\n#define R_PPC_DIAB_SDA21_HI\t181\t/* like EMB_SDA21, but high 16 bit */\n#define R_PPC_DIAB_SDA21_HA\t182\t/* like EMB_SDA21, adjusted high 16 */\n#define R_PPC_DIAB_RELSDA_LO\t183\t/* like EMB_RELSDA, but lower 16 bit */\n#define R_PPC_DIAB_RELSDA_HI\t184\t/* like EMB_RELSDA, but high 16 bit */\n#define R_PPC_DIAB_RELSDA_HA\t185\t/* like EMB_RELSDA, adjusted high 16 */\n\n/* GNU extension to support local ifunc.  */\n#define R_PPC_IRELATIVE\t\t248\n\n/* GNU relocs used in PIC code sequences.  */\n#define R_PPC_REL16\t\t249\t/* half16   (sym+add-.) */\n#define R_PPC_REL16_LO\t\t250\t/* half16   (sym+add-.)@l */\n#define R_PPC_REL16_HI\t\t251\t/* half16   (sym+add-.)@h */\n#define R_PPC_REL16_HA\t\t252\t/* half16   (sym+add-.)@ha */\n\n/* This is a phony reloc to handle any old fashioned TOC16 references\n   that may still be in object files.  */\n#define R_PPC_TOC16\t\t255\n\n/* PowerPC specific values for the Dyn d_tag field.  */\n#define DT_PPC_GOT\t\t(DT_LOPROC + 0)\n#define DT_PPC_NUM\t\t1\n\n/* PowerPC64 relocations defined by the ABIs */\n#define R_PPC64_NONE\t\tR_PPC_NONE\n#define R_PPC64_ADDR32\t\tR_PPC_ADDR32 /* 32bit absolute address */\n#define R_PPC64_ADDR24\t\tR_PPC_ADDR24 /* 26bit address, word aligned */\n#define R_PPC64_ADDR16\t\tR_PPC_ADDR16 /* 16bit absolute address */\n#define R_PPC64_ADDR16_LO\tR_PPC_ADDR16_LO\t/* lower 16bits of address */\n#define R_PPC64_ADDR16_HI\tR_PPC_ADDR16_HI\t/* high 16bits of address. */\n#define R_PPC64_ADDR16_HA\tR_PPC_ADDR16_HA /* adjusted high 16bits.  */\n#define R_PPC64_ADDR14\t\tR_PPC_ADDR14 /* 16bit address, word aligned */\n#define R_PPC64_ADDR14_BRTAKEN\tR_PPC_ADDR14_BRTAKEN\n#define R_PPC64_ADDR14_BRNTAKEN\tR_PPC_ADDR14_BRNTAKEN\n#define R_PPC64_REL24\t\tR_PPC_REL24 /* PC-rel. 26 bit, word aligned */\n#define R_PPC64_REL14\t\tR_PPC_REL14 /* PC relative 16 bit */\n#define R_PPC64_REL14_BRTAKEN\tR_PPC_REL14_BRTAKEN\n#define R_PPC64_REL14_BRNTAKEN\tR_PPC_REL14_BRNTAKEN\n#define R_PPC64_GOT16\t\tR_PPC_GOT16\n#define R_PPC64_GOT16_LO\tR_PPC_GOT16_LO\n#define R_PPC64_GOT16_HI\tR_PPC_GOT16_HI\n#define R_PPC64_GOT16_HA\tR_PPC_GOT16_HA\n\n#define R_PPC64_COPY\t\tR_PPC_COPY\n#define R_PPC64_GLOB_DAT\tR_PPC_GLOB_DAT\n#define R_PPC64_JMP_SLOT\tR_PPC_JMP_SLOT\n#define R_PPC64_RELATIVE\tR_PPC_RELATIVE\n\n#define R_PPC64_UADDR32\t\tR_PPC_UADDR32\n#define R_PPC64_UADDR16\t\tR_PPC_UADDR16\n#define R_PPC64_REL32\t\tR_PPC_REL32\n#define R_PPC64_PLT32\t\tR_PPC_PLT32\n#define R_PPC64_PLTREL32\tR_PPC_PLTREL32\n#define R_PPC64_PLT16_LO\tR_PPC_PLT16_LO\n#define R_PPC64_PLT16_HI\tR_PPC_PLT16_HI\n#define R_PPC64_PLT16_HA\tR_PPC_PLT16_HA\n\n#define R_PPC64_SECTOFF\t\tR_PPC_SECTOFF\n#define R_PPC64_SECTOFF_LO\tR_PPC_SECTOFF_LO\n#define R_PPC64_SECTOFF_HI\tR_PPC_SECTOFF_HI\n#define R_PPC64_SECTOFF_HA\tR_PPC_SECTOFF_HA\n#define R_PPC64_ADDR30\t\t37 /* word30 (S + A - P) >> 2 */\n#define R_PPC64_ADDR64\t\t38 /* doubleword64 S + A */\n#define R_PPC64_ADDR16_HIGHER\t39 /* half16 #higher(S + A) */\n#define R_PPC64_ADDR16_HIGHERA\t40 /* half16 #highera(S + A) */\n#define R_PPC64_ADDR16_HIGHEST\t41 /* half16 #highest(S + A) */\n#define R_PPC64_ADDR16_HIGHESTA\t42 /* half16 #highesta(S + A) */\n#define R_PPC64_UADDR64\t\t43 /* doubleword64 S + A */\n#define R_PPC64_REL64\t\t44 /* doubleword64 S + A - P */\n#define R_PPC64_PLT64\t\t45 /* doubleword64 L + A */\n#define R_PPC64_PLTREL64\t46 /* doubleword64 L + A - P */\n#define R_PPC64_TOC16\t\t47 /* half16* S + A - .TOC */\n#define R_PPC64_TOC16_LO\t48 /* half16 #lo(S + A - .TOC.) */\n#define R_PPC64_TOC16_HI\t49 /* half16 #hi(S + A - .TOC.) */\n#define R_PPC64_TOC16_HA\t50 /* half16 #ha(S + A - .TOC.) */\n#define R_PPC64_TOC\t\t51 /* doubleword64 .TOC */\n#define R_PPC64_PLTGOT16\t52 /* half16* M + A */\n#define R_PPC64_PLTGOT16_LO\t53 /* half16 #lo(M + A) */\n#define R_PPC64_PLTGOT16_HI\t54 /* half16 #hi(M + A) */\n#define R_PPC64_PLTGOT16_HA\t55 /* half16 #ha(M + A) */\n\n#define R_PPC64_ADDR16_DS\t56 /* half16ds* (S + A) >> 2 */\n#define R_PPC64_ADDR16_LO_DS\t57 /* half16ds  #lo(S + A) >> 2 */\n#define R_PPC64_GOT16_DS\t58 /* half16ds* (G + A) >> 2 */\n#define R_PPC64_GOT16_LO_DS\t59 /* half16ds  #lo(G + A) >> 2 */\n#define R_PPC64_PLT16_LO_DS\t60 /* half16ds  #lo(L + A) >> 2 */\n#define R_PPC64_SECTOFF_DS\t61 /* half16ds* (R + A) >> 2 */\n#define R_PPC64_SECTOFF_LO_DS\t62 /* half16ds  #lo(R + A) >> 2 */\n#define R_PPC64_TOC16_DS\t63 /* half16ds* (S + A - .TOC.) >> 2 */\n#define R_PPC64_TOC16_LO_DS\t64 /* half16ds  #lo(S + A - .TOC.) >> 2 */\n#define R_PPC64_PLTGOT16_DS\t65 /* half16ds* (M + A) >> 2 */\n#define R_PPC64_PLTGOT16_LO_DS\t66 /* half16ds  #lo(M + A) >> 2 */\n\n/* PowerPC64 relocations defined for the TLS access ABI.  */\n#define R_PPC64_TLS\t\t67 /* none\t(sym+add)@tls */\n#define R_PPC64_DTPMOD64\t68 /* doubleword64 (sym+add)@dtpmod */\n#define R_PPC64_TPREL16\t\t69 /* half16*\t(sym+add)@tprel */\n#define R_PPC64_TPREL16_LO\t70 /* half16\t(sym+add)@tprel@l */\n#define R_PPC64_TPREL16_HI\t71 /* half16\t(sym+add)@tprel@h */\n#define R_PPC64_TPREL16_HA\t72 /* half16\t(sym+add)@tprel@ha */\n#define R_PPC64_TPREL64\t\t73 /* doubleword64 (sym+add)@tprel */\n#define R_PPC64_DTPREL16\t74 /* half16*\t(sym+add)@dtprel */\n#define R_PPC64_DTPREL16_LO\t75 /* half16\t(sym+add)@dtprel@l */\n#define R_PPC64_DTPREL16_HI\t76 /* half16\t(sym+add)@dtprel@h */\n#define R_PPC64_DTPREL16_HA\t77 /* half16\t(sym+add)@dtprel@ha */\n#define R_PPC64_DTPREL64\t78 /* doubleword64 (sym+add)@dtprel */\n#define R_PPC64_GOT_TLSGD16\t79 /* half16*\t(sym+add)@got@tlsgd */\n#define R_PPC64_GOT_TLSGD16_LO\t80 /* half16\t(sym+add)@got@tlsgd@l */\n#define R_PPC64_GOT_TLSGD16_HI\t81 /* half16\t(sym+add)@got@tlsgd@h */\n#define R_PPC64_GOT_TLSGD16_HA\t82 /* half16\t(sym+add)@got@tlsgd@ha */\n#define R_PPC64_GOT_TLSLD16\t83 /* half16*\t(sym+add)@got@tlsld */\n#define R_PPC64_GOT_TLSLD16_LO\t84 /* half16\t(sym+add)@got@tlsld@l */\n#define R_PPC64_GOT_TLSLD16_HI\t85 /* half16\t(sym+add)@got@tlsld@h */\n#define R_PPC64_GOT_TLSLD16_HA\t86 /* half16\t(sym+add)@got@tlsld@ha */\n#define R_PPC64_GOT_TPREL16_DS\t87 /* half16ds*\t(sym+add)@got@tprel */\n#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */\n#define R_PPC64_GOT_TPREL16_HI\t89 /* half16\t(sym+add)@got@tprel@h */\n#define R_PPC64_GOT_TPREL16_HA\t90 /* half16\t(sym+add)@got@tprel@ha */\n#define R_PPC64_GOT_DTPREL16_DS\t91 /* half16ds*\t(sym+add)@got@dtprel */\n#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */\n#define R_PPC64_GOT_DTPREL16_HI\t93 /* half16\t(sym+add)@got@dtprel@h */\n#define R_PPC64_GOT_DTPREL16_HA\t94 /* half16\t(sym+add)@got@dtprel@ha */\n#define R_PPC64_TPREL16_DS\t95 /* half16ds*\t(sym+add)@tprel */\n#define R_PPC64_TPREL16_LO_DS\t96 /* half16ds\t(sym+add)@tprel@l */\n#define R_PPC64_TPREL16_HIGHER\t97 /* half16\t(sym+add)@tprel@higher */\n#define R_PPC64_TPREL16_HIGHERA\t98 /* half16\t(sym+add)@tprel@highera */\n#define R_PPC64_TPREL16_HIGHEST\t99 /* half16\t(sym+add)@tprel@highest */\n#define R_PPC64_TPREL16_HIGHESTA 100 /* half16\t(sym+add)@tprel@highesta */\n#define R_PPC64_DTPREL16_DS\t101 /* half16ds* (sym+add)@dtprel */\n#define R_PPC64_DTPREL16_LO_DS\t102 /* half16ds\t(sym+add)@dtprel@l */\n#define R_PPC64_DTPREL16_HIGHER\t103 /* half16\t(sym+add)@dtprel@higher */\n#define R_PPC64_DTPREL16_HIGHERA 104 /* half16\t(sym+add)@dtprel@highera */\n#define R_PPC64_DTPREL16_HIGHEST 105 /* half16\t(sym+add)@dtprel@highest */\n#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16\t(sym+add)@dtprel@highesta */\n\n/* GNU extension to support local ifunc.  */\n#define R_PPC64_JMP_IREL\t247\n#define R_PPC64_IRELATIVE\t248\n#define R_PPC64_REL16\t\t249\t/* half16   (sym+add-.) */\n#define R_PPC64_REL16_LO\t250\t/* half16   (sym+add-.)@l */\n#define R_PPC64_REL16_HI\t251\t/* half16   (sym+add-.)@h */\n#define R_PPC64_REL16_HA\t252\t/* half16   (sym+add-.)@ha */\n\n/* PowerPC64 specific values for the Dyn d_tag field.  */\n#define DT_PPC64_GLINK  (DT_LOPROC + 0)\n#define DT_PPC64_OPD\t(DT_LOPROC + 1)\n#define DT_PPC64_OPDSZ\t(DT_LOPROC + 2)\n#define DT_PPC64_NUM    3\n\n\n/* ARM specific declarations */\n\n/* Processor specific flags for the ELF header e_flags field.  */\n#define EF_ARM_RELEXEC\t\t0x01\n#define EF_ARM_HASENTRY\t\t0x02\n#define EF_ARM_INTERWORK\t0x04\n#define EF_ARM_APCS_26\t\t0x08\n#define EF_ARM_APCS_FLOAT\t0x10\n#define EF_ARM_PIC\t\t0x20\n#define EF_ARM_ALIGN8\t\t0x40 /* 8-bit structure alignment is in use */\n#define EF_ARM_NEW_ABI\t\t0x80\n#define EF_ARM_OLD_ABI\t\t0x100\n#define EF_ARM_SOFT_FLOAT\t0x200\n#define EF_ARM_VFP_FLOAT\t0x400\n#define EF_ARM_MAVERICK_FLOAT\t0x800\n\n\n/* Other constants defined in the ARM ELF spec. version B-01.  */\n/* NB. These conflict with values defined above.  */\n#define EF_ARM_SYMSARESORTED\t0x04\n#define EF_ARM_DYNSYMSUSESEGIDX\t0x08\n#define EF_ARM_MAPSYMSFIRST\t0x10\n#define EF_ARM_EABIMASK\t\t0XFF000000\n\n/* Constants defined in AAELF.  */\n#define EF_ARM_BE8\t    0x00800000\n#define EF_ARM_LE8\t    0x00400000\n\n#define EF_ARM_EABI_VERSION(flags)\t((flags) & EF_ARM_EABIMASK)\n#define EF_ARM_EABI_UNKNOWN\t0x00000000\n#define EF_ARM_EABI_VER1\t0x01000000\n#define EF_ARM_EABI_VER2\t0x02000000\n#define EF_ARM_EABI_VER3\t0x03000000\n#define EF_ARM_EABI_VER4\t0x04000000\n#define EF_ARM_EABI_VER5\t0x05000000\n\n/* Additional symbol types for Thumb.  */\n#define STT_ARM_TFUNC\t\tSTT_LOPROC /* A Thumb function.  */\n#define STT_ARM_16BIT\t\tSTT_HIPROC /* A Thumb label.  */\n\n/* ARM-specific values for sh_flags */\n#define SHF_ARM_ENTRYSECT\t0x10000000 /* Section contains an entry point */\n#define SHF_ARM_COMDEF\t\t0x80000000 /* Section may be multiply defined\n\t\t\t\t\t      in the input to a link step.  */\n\n/* ARM-specific program header flags */\n#define PF_ARM_SB\t\t0x10000000 /* Segment contains the location\n\t\t\t\t\t      addressed by the static base. */\n#define PF_ARM_PI\t\t0x20000000 /* Position-independent segment.  */\n#define PF_ARM_ABS\t\t0x40000000 /* Absolute segment.  */\n\n/* Processor specific values for the Phdr p_type field.  */\n#define PT_ARM_EXIDX\t\t(PT_LOPROC + 1)\t/* ARM unwind segment.  */\n\n/* Processor specific values for the Shdr sh_type field.  */\n#define SHT_ARM_EXIDX\t\t(SHT_LOPROC + 1) /* ARM unwind section.  */\n#define SHT_ARM_PREEMPTMAP\t(SHT_LOPROC + 2) /* Preemption details.  */\n#define SHT_ARM_ATTRIBUTES\t(SHT_LOPROC + 3) /* ARM attributes section.  */\n\n\n/* ARM relocs.  */\n\n#define R_ARM_NONE\t\t0\t/* No reloc */\n#define R_ARM_PC24\t\t1\t/* PC relative 26 bit branch */\n#define R_ARM_ABS32\t\t2\t/* Direct 32 bit  */\n#define R_ARM_REL32\t\t3\t/* PC relative 32 bit */\n#define R_ARM_PC13\t\t4\n#define R_ARM_ABS16\t\t5\t/* Direct 16 bit */\n#define R_ARM_ABS12\t\t6\t/* Direct 12 bit */\n#define R_ARM_THM_ABS5\t\t7\n#define R_ARM_ABS8\t\t8\t/* Direct 8 bit */\n#define R_ARM_SBREL32\t\t9\n#define R_ARM_THM_PC22\t\t10\n#define R_ARM_THM_PC8\t\t11\n#define R_ARM_AMP_VCALL9\t12\n#define R_ARM_SWI24\t\t13\t/* Obsolete static relocation.  */\n#define R_ARM_TLS_DESC\t\t13      /* Dynamic relocation.  */\n#define R_ARM_THM_SWI8\t\t14\n#define R_ARM_XPC25\t\t15\n#define R_ARM_THM_XPC22\t\t16\n#define R_ARM_TLS_DTPMOD32\t17\t/* ID of module containing symbol */\n#define R_ARM_TLS_DTPOFF32\t18\t/* Offset in TLS block */\n#define R_ARM_TLS_TPOFF32\t19\t/* Offset in static TLS block */\n#define R_ARM_COPY\t\t20\t/* Copy symbol at runtime */\n#define R_ARM_GLOB_DAT\t\t21\t/* Create GOT entry */\n#define R_ARM_JUMP_SLOT\t\t22\t/* Create PLT entry */\n#define R_ARM_RELATIVE\t\t23\t/* Adjust by program base */\n#define R_ARM_GOTOFF\t\t24\t/* 32 bit offset to GOT */\n#define R_ARM_GOTPC\t\t25\t/* 32 bit PC relative offset to GOT */\n#define R_ARM_GOT32\t\t26\t/* 32 bit GOT entry */\n#define R_ARM_PLT32\t\t27\t/* 32 bit PLT address */\n#define R_ARM_ALU_PCREL_7_0\t32\n#define R_ARM_ALU_PCREL_15_8\t33\n#define R_ARM_ALU_PCREL_23_15\t34\n#define R_ARM_LDR_SBREL_11_0\t35\n#define R_ARM_ALU_SBREL_19_12\t36\n#define R_ARM_ALU_SBREL_27_20\t37\n#define R_ARM_TLS_GOTDESC\t90\n#define R_ARM_TLS_CALL\t\t91\n#define R_ARM_TLS_DESCSEQ\t92\n#define R_ARM_THM_TLS_CALL\t93\n#define R_ARM_GNU_VTENTRY\t100\n#define R_ARM_GNU_VTINHERIT\t101\n#define R_ARM_THM_PC11\t\t102\t/* thumb unconditional branch */\n#define R_ARM_THM_PC9\t\t103\t/* thumb conditional branch */\n#define R_ARM_TLS_GD32\t\t104\t/* PC-rel 32 bit for global dynamic\n\t\t\t\t\t   thread local data */\n#define R_ARM_TLS_LDM32\t\t105\t/* PC-rel 32 bit for local dynamic\n\t\t\t\t\t   thread local data */\n#define R_ARM_TLS_LDO32\t\t106\t/* 32 bit offset relative to TLS\n\t\t\t\t\t   block */\n#define R_ARM_TLS_IE32\t\t107\t/* PC-rel 32 bit for GOT entry of\n\t\t\t\t\t   static TLS block offset */\n#define R_ARM_TLS_LE32\t\t108\t/* 32 bit offset relative to static\n\t\t\t\t\t   TLS block */\n#define\tR_ARM_THM_TLS_DESCSEQ\t129\n#define R_ARM_IRELATIVE\t\t160\n#define R_ARM_RXPC25\t\t249\n#define R_ARM_RSBREL32\t\t250\n#define R_ARM_THM_RPC22\t\t251\n#define R_ARM_RREL32\t\t252\n#define R_ARM_RABS22\t\t253\n#define R_ARM_RPC24\t\t254\n#define R_ARM_RBASE\t\t255\n/* Keep this the last entry.  */\n#define R_ARM_NUM\t\t256\n\n/* IA-64 specific declarations.  */\n\n/* Processor specific flags for the Ehdr e_flags field.  */\n#define EF_IA_64_MASKOS\t\t0x0000000f\t/* os-specific flags */\n#define EF_IA_64_ABI64\t\t0x00000010\t/* 64-bit ABI */\n#define EF_IA_64_ARCH\t\t0xff000000\t/* arch. version mask */\n\n/* Processor specific values for the Phdr p_type field.  */\n#define PT_IA_64_ARCHEXT\t(PT_LOPROC + 0)\t/* arch extension bits */\n#define PT_IA_64_UNWIND\t\t(PT_LOPROC + 1)\t/* ia64 unwind bits */\n#define PT_IA_64_HP_OPT_ANOT\t(PT_LOOS + 0x12)\n#define PT_IA_64_HP_HSL_ANOT\t(PT_LOOS + 0x13)\n#define PT_IA_64_HP_STACK\t(PT_LOOS + 0x14)\n\n/* Processor specific flags for the Phdr p_flags field.  */\n#define PF_IA_64_NORECOV\t0x80000000\t/* spec insns w/o recovery */\n\n/* Processor specific values for the Shdr sh_type field.  */\n#define SHT_IA_64_EXT\t\t(SHT_LOPROC + 0) /* extension bits */\n#define SHT_IA_64_UNWIND\t(SHT_LOPROC + 1) /* unwind bits */\n\n/* Processor specific flags for the Shdr sh_flags field.  */\n#define SHF_IA_64_SHORT\t\t0x10000000\t/* section near gp */\n#define SHF_IA_64_NORECOV\t0x20000000\t/* spec insns w/o recovery */\n\n/* Processor specific values for the Dyn d_tag field.  */\n#define DT_IA_64_PLT_RESERVE\t(DT_LOPROC + 0)\n#define DT_IA_64_NUM\t\t1\n\n/* IA-64 relocations.  */\n#define R_IA64_NONE\t\t0x00\t/* none */\n#define R_IA64_IMM14\t\t0x21\t/* symbol + addend, add imm14 */\n#define R_IA64_IMM22\t\t0x22\t/* symbol + addend, add imm22 */\n#define R_IA64_IMM64\t\t0x23\t/* symbol + addend, mov imm64 */\n#define R_IA64_DIR32MSB\t\t0x24\t/* symbol + addend, data4 MSB */\n#define R_IA64_DIR32LSB\t\t0x25\t/* symbol + addend, data4 LSB */\n#define R_IA64_DIR64MSB\t\t0x26\t/* symbol + addend, data8 MSB */\n#define R_IA64_DIR64LSB\t\t0x27\t/* symbol + addend, data8 LSB */\n#define R_IA64_GPREL22\t\t0x2a\t/* @gprel(sym + add), add imm22 */\n#define R_IA64_GPREL64I\t\t0x2b\t/* @gprel(sym + add), mov imm64 */\n#define R_IA64_GPREL32MSB\t0x2c\t/* @gprel(sym + add), data4 MSB */\n#define R_IA64_GPREL32LSB\t0x2d\t/* @gprel(sym + add), data4 LSB */\n#define R_IA64_GPREL64MSB\t0x2e\t/* @gprel(sym + add), data8 MSB */\n#define R_IA64_GPREL64LSB\t0x2f\t/* @gprel(sym + add), data8 LSB */\n#define R_IA64_LTOFF22\t\t0x32\t/* @ltoff(sym + add), add imm22 */\n#define R_IA64_LTOFF64I\t\t0x33\t/* @ltoff(sym + add), mov imm64 */\n#define R_IA64_PLTOFF22\t\t0x3a\t/* @pltoff(sym + add), add imm22 */\n#define R_IA64_PLTOFF64I\t0x3b\t/* @pltoff(sym + add), mov imm64 */\n#define R_IA64_PLTOFF64MSB\t0x3e\t/* @pltoff(sym + add), data8 MSB */\n#define R_IA64_PLTOFF64LSB\t0x3f\t/* @pltoff(sym + add), data8 LSB */\n#define R_IA64_FPTR64I\t\t0x43\t/* @fptr(sym + add), mov imm64 */\n#define R_IA64_FPTR32MSB\t0x44\t/* @fptr(sym + add), data4 MSB */\n#define R_IA64_FPTR32LSB\t0x45\t/* @fptr(sym + add), data4 LSB */\n#define R_IA64_FPTR64MSB\t0x46\t/* @fptr(sym + add), data8 MSB */\n#define R_IA64_FPTR64LSB\t0x47\t/* @fptr(sym + add), data8 LSB */\n#define R_IA64_PCREL60B\t\t0x48\t/* @pcrel(sym + add), brl */\n#define R_IA64_PCREL21B\t\t0x49\t/* @pcrel(sym + add), ptb, call */\n#define R_IA64_PCREL21M\t\t0x4a\t/* @pcrel(sym + add), chk.s */\n#define R_IA64_PCREL21F\t\t0x4b\t/* @pcrel(sym + add), fchkf */\n#define R_IA64_PCREL32MSB\t0x4c\t/* @pcrel(sym + add), data4 MSB */\n#define R_IA64_PCREL32LSB\t0x4d\t/* @pcrel(sym + add), data4 LSB */\n#define R_IA64_PCREL64MSB\t0x4e\t/* @pcrel(sym + add), data8 MSB */\n#define R_IA64_PCREL64LSB\t0x4f\t/* @pcrel(sym + add), data8 LSB */\n#define R_IA64_LTOFF_FPTR22\t0x52\t/* @ltoff(@fptr(s+a)), imm22 */\n#define R_IA64_LTOFF_FPTR64I\t0x53\t/* @ltoff(@fptr(s+a)), imm64 */\n#define R_IA64_LTOFF_FPTR32MSB\t0x54\t/* @ltoff(@fptr(s+a)), data4 MSB */\n#define R_IA64_LTOFF_FPTR32LSB\t0x55\t/* @ltoff(@fptr(s+a)), data4 LSB */\n#define R_IA64_LTOFF_FPTR64MSB\t0x56\t/* @ltoff(@fptr(s+a)), data8 MSB */\n#define R_IA64_LTOFF_FPTR64LSB\t0x57\t/* @ltoff(@fptr(s+a)), data8 LSB */\n#define R_IA64_SEGREL32MSB\t0x5c\t/* @segrel(sym + add), data4 MSB */\n#define R_IA64_SEGREL32LSB\t0x5d\t/* @segrel(sym + add), data4 LSB */\n#define R_IA64_SEGREL64MSB\t0x5e\t/* @segrel(sym + add), data8 MSB */\n#define R_IA64_SEGREL64LSB\t0x5f\t/* @segrel(sym + add), data8 LSB */\n#define R_IA64_SECREL32MSB\t0x64\t/* @secrel(sym + add), data4 MSB */\n#define R_IA64_SECREL32LSB\t0x65\t/* @secrel(sym + add), data4 LSB */\n#define R_IA64_SECREL64MSB\t0x66\t/* @secrel(sym + add), data8 MSB */\n#define R_IA64_SECREL64LSB\t0x67\t/* @secrel(sym + add), data8 LSB */\n#define R_IA64_REL32MSB\t\t0x6c\t/* data 4 + REL */\n#define R_IA64_REL32LSB\t\t0x6d\t/* data 4 + REL */\n#define R_IA64_REL64MSB\t\t0x6e\t/* data 8 + REL */\n#define R_IA64_REL64LSB\t\t0x6f\t/* data 8 + REL */\n#define R_IA64_LTV32MSB\t\t0x74\t/* symbol + addend, data4 MSB */\n#define R_IA64_LTV32LSB\t\t0x75\t/* symbol + addend, data4 LSB */\n#define R_IA64_LTV64MSB\t\t0x76\t/* symbol + addend, data8 MSB */\n#define R_IA64_LTV64LSB\t\t0x77\t/* symbol + addend, data8 LSB */\n#define R_IA64_PCREL21BI\t0x79\t/* @pcrel(sym + add), 21bit inst */\n#define R_IA64_PCREL22\t\t0x7a\t/* @pcrel(sym + add), 22bit inst */\n#define R_IA64_PCREL64I\t\t0x7b\t/* @pcrel(sym + add), 64bit inst */\n#define R_IA64_IPLTMSB\t\t0x80\t/* dynamic reloc, imported PLT, MSB */\n#define R_IA64_IPLTLSB\t\t0x81\t/* dynamic reloc, imported PLT, LSB */\n#define R_IA64_COPY\t\t0x84\t/* copy relocation */\n#define R_IA64_SUB\t\t0x85\t/* Addend and symbol difference */\n#define R_IA64_LTOFF22X\t\t0x86\t/* LTOFF22, relaxable.  */\n#define R_IA64_LDXMOV\t\t0x87\t/* Use of LTOFF22X.  */\n#define R_IA64_TPREL14\t\t0x91\t/* @tprel(sym + add), imm14 */\n#define R_IA64_TPREL22\t\t0x92\t/* @tprel(sym + add), imm22 */\n#define R_IA64_TPREL64I\t\t0x93\t/* @tprel(sym + add), imm64 */\n#define R_IA64_TPREL64MSB\t0x96\t/* @tprel(sym + add), data8 MSB */\n#define R_IA64_TPREL64LSB\t0x97\t/* @tprel(sym + add), data8 LSB */\n#define R_IA64_LTOFF_TPREL22\t0x9a\t/* @ltoff(@tprel(s+a)), imm2 */\n#define R_IA64_DTPMOD64MSB\t0xa6\t/* @dtpmod(sym + add), data8 MSB */\n#define R_IA64_DTPMOD64LSB\t0xa7\t/* @dtpmod(sym + add), data8 LSB */\n#define R_IA64_LTOFF_DTPMOD22\t0xaa\t/* @ltoff(@dtpmod(sym + add)), imm22 */\n#define R_IA64_DTPREL14\t\t0xb1\t/* @dtprel(sym + add), imm14 */\n#define R_IA64_DTPREL22\t\t0xb2\t/* @dtprel(sym + add), imm22 */\n#define R_IA64_DTPREL64I\t0xb3\t/* @dtprel(sym + add), imm64 */\n#define R_IA64_DTPREL32MSB\t0xb4\t/* @dtprel(sym + add), data4 MSB */\n#define R_IA64_DTPREL32LSB\t0xb5\t/* @dtprel(sym + add), data4 LSB */\n#define R_IA64_DTPREL64MSB\t0xb6\t/* @dtprel(sym + add), data8 MSB */\n#define R_IA64_DTPREL64LSB\t0xb7\t/* @dtprel(sym + add), data8 LSB */\n#define R_IA64_LTOFF_DTPREL22\t0xba\t/* @ltoff(@dtprel(s+a)), imm22 */\n\n/* SH specific declarations */\n\n/* Processor specific flags for the ELF header e_flags field.  */\n#define EF_SH_MACH_MASK\t\t0x1f\n#define EF_SH_UNKNOWN\t\t0x0\n#define EF_SH1\t\t\t0x1\n#define EF_SH2\t\t\t0x2\n#define EF_SH3\t\t\t0x3\n#define EF_SH_DSP\t\t0x4\n#define EF_SH3_DSP\t\t0x5\n#define EF_SH4AL_DSP\t\t0x6\n#define EF_SH3E\t\t\t0x8\n#define EF_SH4\t\t\t0x9\n#define EF_SH2E\t\t\t0xb\n#define EF_SH4A\t\t\t0xc\n#define EF_SH2A\t\t\t0xd\n#define EF_SH4_NOFPU\t\t0x10\n#define EF_SH4A_NOFPU\t\t0x11\n#define EF_SH4_NOMMU_NOFPU\t0x12\n#define EF_SH2A_NOFPU\t\t0x13\n#define EF_SH3_NOMMU\t\t0x14\n#define EF_SH2A_SH4_NOFPU\t0x15\n#define EF_SH2A_SH3_NOFPU\t0x16\n#define EF_SH2A_SH4\t\t0x17\n#define EF_SH2A_SH3E\t\t0x18\n\n/* SH relocs.  */\n#define\tR_SH_NONE\t\t0\n#define\tR_SH_DIR32\t\t1\n#define\tR_SH_REL32\t\t2\n#define\tR_SH_DIR8WPN\t\t3\n#define\tR_SH_IND12W\t\t4\n#define\tR_SH_DIR8WPL\t\t5\n#define\tR_SH_DIR8WPZ\t\t6\n#define\tR_SH_DIR8BP\t\t7\n#define\tR_SH_DIR8W\t\t8\n#define\tR_SH_DIR8L\t\t9\n#define\tR_SH_SWITCH16\t\t25\n#define\tR_SH_SWITCH32\t\t26\n#define\tR_SH_USES\t\t27\n#define\tR_SH_COUNT\t\t28\n#define\tR_SH_ALIGN\t\t29\n#define\tR_SH_CODE\t\t30\n#define\tR_SH_DATA\t\t31\n#define\tR_SH_LABEL\t\t32\n#define\tR_SH_SWITCH8\t\t33\n#define\tR_SH_GNU_VTINHERIT\t34\n#define\tR_SH_GNU_VTENTRY\t35\n#define\tR_SH_TLS_GD_32\t\t144\n#define\tR_SH_TLS_LD_32\t\t145\n#define\tR_SH_TLS_LDO_32\t\t146\n#define\tR_SH_TLS_IE_32\t\t147\n#define\tR_SH_TLS_LE_32\t\t148\n#define\tR_SH_TLS_DTPMOD32\t149\n#define\tR_SH_TLS_DTPOFF32\t150\n#define\tR_SH_TLS_TPOFF32\t151\n#define\tR_SH_GOT32\t\t160\n#define\tR_SH_PLT32\t\t161\n#define\tR_SH_COPY\t\t162\n#define\tR_SH_GLOB_DAT\t\t163\n#define\tR_SH_JMP_SLOT\t\t164\n#define\tR_SH_RELATIVE\t\t165\n#define\tR_SH_GOTOFF\t\t166\n#define\tR_SH_GOTPC\t\t167\n/* Keep this the last entry.  */\n#define\tR_SH_NUM\t\t256\n\n/* S/390 specific definitions.  */\n\n/* Valid values for the e_flags field.  */\n\n#define EF_S390_HIGH_GPRS    0x00000001  /* High GPRs kernel facility needed.  */\n\n/* Additional s390 relocs */\n\n#define R_390_NONE\t\t0\t/* No reloc.  */\n#define R_390_8\t\t\t1\t/* Direct 8 bit.  */\n#define R_390_12\t\t2\t/* Direct 12 bit.  */\n#define R_390_16\t\t3\t/* Direct 16 bit.  */\n#define R_390_32\t\t4\t/* Direct 32 bit.  */\n#define R_390_PC32\t\t5\t/* PC relative 32 bit.\t*/\n#define R_390_GOT12\t\t6\t/* 12 bit GOT offset.  */\n#define R_390_GOT32\t\t7\t/* 32 bit GOT offset.  */\n#define R_390_PLT32\t\t8\t/* 32 bit PC relative PLT address.  */\n#define R_390_COPY\t\t9\t/* Copy symbol at runtime.  */\n#define R_390_GLOB_DAT\t\t10\t/* Create GOT entry.  */\n#define R_390_JMP_SLOT\t\t11\t/* Create PLT entry.  */\n#define R_390_RELATIVE\t\t12\t/* Adjust by program base.  */\n#define R_390_GOTOFF32\t\t13\t/* 32 bit offset to GOT.\t */\n#define R_390_GOTPC\t\t14\t/* 32 bit PC relative offset to GOT.  */\n#define R_390_GOT16\t\t15\t/* 16 bit GOT offset.  */\n#define R_390_PC16\t\t16\t/* PC relative 16 bit.\t*/\n#define R_390_PC16DBL\t\t17\t/* PC relative 16 bit shifted by 1.  */\n#define R_390_PLT16DBL\t\t18\t/* 16 bit PC rel. PLT shifted by 1.  */\n#define R_390_PC32DBL\t\t19\t/* PC relative 32 bit shifted by 1.  */\n#define R_390_PLT32DBL\t\t20\t/* 32 bit PC rel. PLT shifted by 1.  */\n#define R_390_GOTPCDBL\t\t21\t/* 32 bit PC rel. GOT shifted by 1.  */\n#define R_390_64\t\t22\t/* Direct 64 bit.  */\n#define R_390_PC64\t\t23\t/* PC relative 64 bit.\t*/\n#define R_390_GOT64\t\t24\t/* 64 bit GOT offset.  */\n#define R_390_PLT64\t\t25\t/* 64 bit PC relative PLT address.  */\n#define R_390_GOTENT\t\t26\t/* 32 bit PC rel. to GOT entry >> 1. */\n#define R_390_GOTOFF16\t\t27\t/* 16 bit offset to GOT. */\n#define R_390_GOTOFF64\t\t28\t/* 64 bit offset to GOT. */\n#define R_390_GOTPLT12\t\t29\t/* 12 bit offset to jump slot.\t*/\n#define R_390_GOTPLT16\t\t30\t/* 16 bit offset to jump slot.\t*/\n#define R_390_GOTPLT32\t\t31\t/* 32 bit offset to jump slot.\t*/\n#define R_390_GOTPLT64\t\t32\t/* 64 bit offset to jump slot.\t*/\n#define R_390_GOTPLTENT\t\t33\t/* 32 bit rel. offset to jump slot.  */\n#define R_390_PLTOFF16\t\t34\t/* 16 bit offset from GOT to PLT. */\n#define R_390_PLTOFF32\t\t35\t/* 32 bit offset from GOT to PLT. */\n#define R_390_PLTOFF64\t\t36\t/* 16 bit offset from GOT to PLT. */\n#define R_390_TLS_LOAD\t\t37\t/* Tag for load insn in TLS code.  */\n#define R_390_TLS_GDCALL\t38\t/* Tag for function call in general\n\t\t\t\t\t   dynamic TLS code. */\n#define R_390_TLS_LDCALL\t39\t/* Tag for function call in local\n\t\t\t\t\t   dynamic TLS code. */\n#define R_390_TLS_GD32\t\t40\t/* Direct 32 bit for general dynamic\n\t\t\t\t\t   thread local data.  */\n#define R_390_TLS_GD64\t\t41\t/* Direct 64 bit for general dynamic\n\t\t\t\t\t  thread local data.  */\n#define R_390_TLS_GOTIE12\t42\t/* 12 bit GOT offset for static TLS\n\t\t\t\t\t   block offset.  */\n#define R_390_TLS_GOTIE32\t43\t/* 32 bit GOT offset for static TLS\n\t\t\t\t\t   block offset.  */\n#define R_390_TLS_GOTIE64\t44\t/* 64 bit GOT offset for static TLS\n\t\t\t\t\t   block offset. */\n#define R_390_TLS_LDM32\t\t45\t/* Direct 32 bit for local dynamic\n\t\t\t\t\t   thread local data in LE code.  */\n#define R_390_TLS_LDM64\t\t46\t/* Direct 64 bit for local dynamic\n\t\t\t\t\t   thread local data in LE code.  */\n#define R_390_TLS_IE32\t\t47\t/* 32 bit address of GOT entry for\n\t\t\t\t\t   negated static TLS block offset.  */\n#define R_390_TLS_IE64\t\t48\t/* 64 bit address of GOT entry for\n\t\t\t\t\t   negated static TLS block offset.  */\n#define R_390_TLS_IEENT\t\t49\t/* 32 bit rel. offset to GOT entry for\n\t\t\t\t\t   negated static TLS block offset.  */\n#define R_390_TLS_LE32\t\t50\t/* 32 bit negated offset relative to\n\t\t\t\t\t   static TLS block.  */\n#define R_390_TLS_LE64\t\t51\t/* 64 bit negated offset relative to\n\t\t\t\t\t   static TLS block.  */\n#define R_390_TLS_LDO32\t\t52\t/* 32 bit offset relative to TLS\n\t\t\t\t\t   block.  */\n#define R_390_TLS_LDO64\t\t53\t/* 64 bit offset relative to TLS\n\t\t\t\t\t   block.  */\n#define R_390_TLS_DTPMOD\t54\t/* ID of module containing symbol.  */\n#define R_390_TLS_DTPOFF\t55\t/* Offset in TLS block.\t */\n#define R_390_TLS_TPOFF\t\t56\t/* Negated offset in static TLS\n\t\t\t\t\t   block.  */\n#define R_390_20\t\t57\t/* Direct 20 bit.  */\n#define R_390_GOT20\t\t58\t/* 20 bit GOT offset.  */\n#define R_390_GOTPLT20\t\t59\t/* 20 bit offset to jump slot.  */\n#define R_390_TLS_GOTIE20\t60\t/* 20 bit GOT offset for static TLS\n\t\t\t\t\t   block offset.  */\n/* Keep this the last entry.  */\n#define R_390_NUM\t\t61\n\n\n/* CRIS relocations.  */\n#define R_CRIS_NONE\t\t0\n#define R_CRIS_8\t\t1\n#define R_CRIS_16\t\t2\n#define R_CRIS_32\t\t3\n#define R_CRIS_8_PCREL\t\t4\n#define R_CRIS_16_PCREL\t\t5\n#define R_CRIS_32_PCREL\t\t6\n#define R_CRIS_GNU_VTINHERIT\t7\n#define R_CRIS_GNU_VTENTRY\t8\n#define R_CRIS_COPY\t\t9\n#define R_CRIS_GLOB_DAT\t\t10\n#define R_CRIS_JUMP_SLOT\t11\n#define R_CRIS_RELATIVE\t\t12\n#define R_CRIS_16_GOT\t\t13\n#define R_CRIS_32_GOT\t\t14\n#define R_CRIS_16_GOTPLT\t15\n#define R_CRIS_32_GOTPLT\t16\n#define R_CRIS_32_GOTREL\t17\n#define R_CRIS_32_PLT_GOTREL\t18\n#define R_CRIS_32_PLT_PCREL\t19\n\n#define R_CRIS_NUM\t\t20\n\n\n/* AMD x86-64 relocations.  */\n#define R_X86_64_NONE\t\t0\t/* No reloc */\n#define R_X86_64_64\t\t1\t/* Direct 64 bit  */\n#define R_X86_64_PC32\t\t2\t/* PC relative 32 bit signed */\n#define R_X86_64_GOT32\t\t3\t/* 32 bit GOT entry */\n#define R_X86_64_PLT32\t\t4\t/* 32 bit PLT address */\n#define R_X86_64_COPY\t\t5\t/* Copy symbol at runtime */\n#define R_X86_64_GLOB_DAT\t6\t/* Create GOT entry */\n#define R_X86_64_JUMP_SLOT\t7\t/* Create PLT entry */\n#define R_X86_64_RELATIVE\t8\t/* Adjust by program base */\n#define R_X86_64_GOTPCREL\t9\t/* 32 bit signed PC relative\n\t\t\t\t\t   offset to GOT */\n#define R_X86_64_32\t\t10\t/* Direct 32 bit zero extended */\n#define R_X86_64_32S\t\t11\t/* Direct 32 bit sign extended */\n#define R_X86_64_16\t\t12\t/* Direct 16 bit zero extended */\n#define R_X86_64_PC16\t\t13\t/* 16 bit sign extended pc relative */\n#define R_X86_64_8\t\t14\t/* Direct 8 bit sign extended  */\n#define R_X86_64_PC8\t\t15\t/* 8 bit sign extended pc relative */\n#define R_X86_64_DTPMOD64\t16\t/* ID of module containing symbol */\n#define R_X86_64_DTPOFF64\t17\t/* Offset in module's TLS block */\n#define R_X86_64_TPOFF64\t18\t/* Offset in initial TLS block */\n#define R_X86_64_TLSGD\t\t19\t/* 32 bit signed PC relative offset\n\t\t\t\t\t   to two GOT entries for GD symbol */\n#define R_X86_64_TLSLD\t\t20\t/* 32 bit signed PC relative offset\n\t\t\t\t\t   to two GOT entries for LD symbol */\n#define R_X86_64_DTPOFF32\t21\t/* Offset in TLS block */\n#define R_X86_64_GOTTPOFF\t22\t/* 32 bit signed PC relative offset\n\t\t\t\t\t   to GOT entry for IE symbol */\n#define R_X86_64_TPOFF32\t23\t/* Offset in initial TLS block */\n#define R_X86_64_PC64\t\t24\t/* PC relative 64 bit */\n#define R_X86_64_GOTOFF64\t25\t/* 64 bit offset to GOT */\n#define R_X86_64_GOTPC32\t26\t/* 32 bit signed pc relative\n\t\t\t\t\t   offset to GOT */\n#define R_X86_64_GOT64\t\t27\t/* 64-bit GOT entry offset */\n#define R_X86_64_GOTPCREL64\t28\t/* 64-bit PC relative offset\n\t\t\t\t\t   to GOT entry */\n#define R_X86_64_GOTPC64\t29\t/* 64-bit PC relative offset to GOT */\n#define R_X86_64_GOTPLT64\t30 \t/* like GOT64, says PLT entry needed */\n#define R_X86_64_PLTOFF64\t31\t/* 64-bit GOT relative offset\n\t\t\t\t\t   to PLT entry */\n#define R_X86_64_SIZE32\t\t32\t/* Size of symbol plus 32-bit addend */\n#define R_X86_64_SIZE64\t\t33\t/* Size of symbol plus 64-bit addend */\n#define R_X86_64_GOTPC32_TLSDESC 34\t/* GOT offset for TLS descriptor.  */\n#define R_X86_64_TLSDESC_CALL   35\t/* Marker for call through TLS\n\t\t\t\t\t   descriptor.  */\n#define R_X86_64_TLSDESC        36\t/* TLS descriptor.  */\n#define R_X86_64_IRELATIVE\t37\t/* Adjust indirectly by program base */\n\n#define R_X86_64_NUM\t\t38\n\n\n/* AM33 relocations.  */\n#define R_MN10300_NONE\t\t0\t/* No reloc.  */\n#define R_MN10300_32\t\t1\t/* Direct 32 bit.  */\n#define R_MN10300_16\t\t2\t/* Direct 16 bit.  */\n#define R_MN10300_8\t\t3\t/* Direct 8 bit.  */\n#define R_MN10300_PCREL32\t4\t/* PC-relative 32-bit.  */\n#define R_MN10300_PCREL16\t5\t/* PC-relative 16-bit signed.  */\n#define R_MN10300_PCREL8\t6\t/* PC-relative 8-bit signed.  */\n#define R_MN10300_GNU_VTINHERIT\t7\t/* Ancient C++ vtable garbage... */\n#define R_MN10300_GNU_VTENTRY\t8\t/* ... collection annotation.  */\n#define R_MN10300_24\t\t9\t/* Direct 24 bit.  */\n#define R_MN10300_GOTPC32\t10\t/* 32-bit PCrel offset to GOT.  */\n#define R_MN10300_GOTPC16\t11\t/* 16-bit PCrel offset to GOT.  */\n#define R_MN10300_GOTOFF32\t12\t/* 32-bit offset from GOT.  */\n#define R_MN10300_GOTOFF24\t13\t/* 24-bit offset from GOT.  */\n#define R_MN10300_GOTOFF16\t14\t/* 16-bit offset from GOT.  */\n#define R_MN10300_PLT32\t\t15\t/* 32-bit PCrel to PLT entry.  */\n#define R_MN10300_PLT16\t\t16\t/* 16-bit PCrel to PLT entry.  */\n#define R_MN10300_GOT32\t\t17\t/* 32-bit offset to GOT entry.  */\n#define R_MN10300_GOT24\t\t18\t/* 24-bit offset to GOT entry.  */\n#define R_MN10300_GOT16\t\t19\t/* 16-bit offset to GOT entry.  */\n#define R_MN10300_COPY\t\t20\t/* Copy symbol at runtime.  */\n#define R_MN10300_GLOB_DAT\t21\t/* Create GOT entry.  */\n#define R_MN10300_JMP_SLOT\t22\t/* Create PLT entry.  */\n#define R_MN10300_RELATIVE\t23\t/* Adjust by program base.  */\n\n#define R_MN10300_NUM\t\t24\n\n\n/* M32R relocs.  */\n#define R_M32R_NONE\t\t0\t/* No reloc. */\n#define R_M32R_16\t\t1\t/* Direct 16 bit. */\n#define R_M32R_32\t\t2\t/* Direct 32 bit. */\n#define R_M32R_24\t\t3\t/* Direct 24 bit. */\n#define R_M32R_10_PCREL\t\t4\t/* PC relative 10 bit shifted. */\n#define R_M32R_18_PCREL\t\t5\t/* PC relative 18 bit shifted. */\n#define R_M32R_26_PCREL\t\t6\t/* PC relative 26 bit shifted. */\n#define R_M32R_HI16_ULO\t\t7\t/* High 16 bit with unsigned low. */\n#define R_M32R_HI16_SLO\t\t8\t/* High 16 bit with signed low. */\n#define R_M32R_LO16\t\t9\t/* Low 16 bit. */\n#define R_M32R_SDA16\t\t10\t/* 16 bit offset in SDA. */\n#define R_M32R_GNU_VTINHERIT\t11\n#define R_M32R_GNU_VTENTRY\t12\n/* M32R relocs use SHT_RELA.  */\n#define R_M32R_16_RELA\t\t33\t/* Direct 16 bit. */\n#define R_M32R_32_RELA\t\t34\t/* Direct 32 bit. */\n#define R_M32R_24_RELA\t\t35\t/* Direct 24 bit. */\n#define R_M32R_10_PCREL_RELA\t36\t/* PC relative 10 bit shifted. */\n#define R_M32R_18_PCREL_RELA\t37\t/* PC relative 18 bit shifted. */\n#define R_M32R_26_PCREL_RELA\t38\t/* PC relative 26 bit shifted. */\n#define R_M32R_HI16_ULO_RELA\t39\t/* High 16 bit with unsigned low */\n#define R_M32R_HI16_SLO_RELA\t40\t/* High 16 bit with signed low */\n#define R_M32R_LO16_RELA\t41\t/* Low 16 bit */\n#define R_M32R_SDA16_RELA\t42\t/* 16 bit offset in SDA */\n#define R_M32R_RELA_GNU_VTINHERIT\t43\n#define R_M32R_RELA_GNU_VTENTRY\t44\n#define R_M32R_REL32\t\t45\t/* PC relative 32 bit.  */\n\n#define R_M32R_GOT24\t\t48\t/* 24 bit GOT entry */\n#define R_M32R_26_PLTREL\t49\t/* 26 bit PC relative to PLT shifted */\n#define R_M32R_COPY\t\t50\t/* Copy symbol at runtime */\n#define R_M32R_GLOB_DAT\t\t51\t/* Create GOT entry */\n#define R_M32R_JMP_SLOT\t\t52\t/* Create PLT entry */\n#define R_M32R_RELATIVE\t\t53\t/* Adjust by program base */\n#define R_M32R_GOTOFF\t\t54\t/* 24 bit offset to GOT */\n#define R_M32R_GOTPC24\t\t55\t/* 24 bit PC relative offset to GOT */\n#define R_M32R_GOT16_HI_ULO\t56\t/* High 16 bit GOT entry with unsigned\n\t\t\t\t\t   low */\n#define R_M32R_GOT16_HI_SLO\t57\t/* High 16 bit GOT entry with signed\n\t\t\t\t\t   low */\n#define R_M32R_GOT16_LO\t\t58\t/* Low 16 bit GOT entry */\n#define R_M32R_GOTPC_HI_ULO\t59\t/* High 16 bit PC relative offset to\n\t\t\t\t\t   GOT with unsigned low */\n#define R_M32R_GOTPC_HI_SLO\t60\t/* High 16 bit PC relative offset to\n\t\t\t\t\t   GOT with signed low */\n#define R_M32R_GOTPC_LO\t\t61\t/* Low 16 bit PC relative offset to\n\t\t\t\t\t   GOT */\n#define R_M32R_GOTOFF_HI_ULO\t62\t/* High 16 bit offset to GOT\n\t\t\t\t\t   with unsigned low */\n#define R_M32R_GOTOFF_HI_SLO\t63\t/* High 16 bit offset to GOT\n\t\t\t\t\t   with signed low */\n#define R_M32R_GOTOFF_LO\t64\t/* Low 16 bit offset to GOT */\n#define R_M32R_NUM\t\t256\t/* Keep this the last entry. */\n\n\n__END_DECLS\n\n#endif\t/* elf.h */\n"
  },
  {
    "path": "include/philips.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#ifndef __PHILIPS_H\n#define __PHILIPS_H\n\n#include <stdint.h>\n#include \"config.h\"\n\n#define PHILIPS_FUSION1_MAGIC \"NFWB\"\n\n//partition table start = headerSize\n\nstruct philips_fusion1_part {\n\tuint32_t unk0;\n\tuint32_t unk1;\n\tuint32_t unk2;\n\tuint32_t unk3;\n\tuint32_t index;\n\tuint32_t size;\n\tuint32_t offset;\n};\n\nstruct philips_fusion1_upg {\n\tuint32_t magic;\n\tuint32_t flags;\n\tuint32_t headerSize;\n\tuint32_t padding[5];\n\tuint8_t unk[16]; //crc or hash?\n\tuint32_t unk0; //part of unk?\n\n\tuint32_t numPartitions;\n\tuint32_t firstPartition; //offset of first part\n};\n\nvoid extract_philips_fusion1(MFILE *mf, config_opts_t *config_opts);\nMFILE *is_philips_fusion1(const char *filename);\n#endif\n"
  },
  {
    "path": "include/realtek/rtsplit.h",
    "content": "#ifndef __RT_AVSPLIT_H__\n#define __RT_AVSPLIT_H__\n\n#define HEADER_AUDIO1_IMAGE\t0x5353beef\n#define HEADER_AUDIO2_IMAGE\t0x4141beef\n#define HEADER_VIDEO1_IMAGE\t0x5656beef\n#define HEADER_VIDEO2_IMAGE\t0x7878beef\n\ntypedef struct _kernel_image_header {\n   unsigned int magic;\n   unsigned int offset;\n   unsigned int size;\n   unsigned int version;\n   unsigned int reserved[4];\n} kernel_image_header;\n\n#endif // __RT_AVSPLIT_H__\n\n"
  },
  {
    "path": "include/realtek.h",
    "content": "#ifndef __REALTEK_H\n#define __REALTEK_H\n\n#include \"mfile.h\"\nMFILE *is_rtk_bspfw(const char *filename);\nvoid split_rtk_bspfw(MFILE *mf, const char *destdir);\n\n\n#endif\n"
  },
  {
    "path": "include/sniptype.h",
    "content": "/*\n**  SNIPTYPE.H - Include file for SNIPPETS data types and commonly used macros\n*/\n\n#ifndef SNIPTYPE__H\n#    define SNIPTYPE__H\n\n#    include <stdlib.h>\t\t\t/* For free()           */\n#    include <string.h>\t\t\t/* For NULL & strlen()  */\n\ntypedef enum { Error_ = -1, Success_, False_ = 0, True_ } Boolean_T;\n\n#    if defined(__unix__)\ntypedef unsigned char BYTE;\ntypedef unsigned long DWORD;\ntypedef unsigned short WORD;\n#        if !defined(FAR)\n#            define FAR\n#        endif\n#        if !defined(NEAR)\n#            define NEAR\n#        endif\n#        if !defined(HUGE)\n#            define HUGE\n#        endif\n#        if !defined(PASCAL)\n#            define PASCAL\n#        endif\n#        if !defined(CDECL)\n#            define CDECL\n#        endif\n#        if !defined(INTERRUPT)\n#            define INTERRUPT\n#        endif\n#    elif !defined(WIN32) && !defined(_WIN32) && !defined(__NT__) \\\n      && !defined(_WINDOWS)\n#        if !defined(OS2)\ntypedef unsigned char BYTE;\ntypedef unsigned long DWORD;\n#        endif\ntypedef unsigned short WORD;\n#    else\n#        define WIN32_LEAN_AND_MEAN\n#        define NOGDI\n#        define NOSERVICE\n#        undef INC_OLE1\n#        undef INC_OLE2\n#        include <windows.h>\n#        define HUGE\n#    endif\n\ntypedef union {\n\tsigned char c;\n\tBYTE b;\n} VAR8_;\n\ntypedef union {\n\tVAR8_ v8[2];\n\tsigned short s;\n\tWORD w;\n} VAR16_;\n\ntypedef union {\n\tVAR16_ v16[2];\n\tsigned long l;\n\tDWORD dw;\n\tfloat f;\n\tvoid *p;\n} VAR32_;\n\ntypedef union {\n\tVAR32_ v32[2];\n\tdouble d;\n} VAR64_;\n\n#    define NUL '\\0'\n#    define LAST_CHAR(s) (((char *)s)[strlen(s) - 1])\n#    define TOBOOL(x) (!(!(x)))\n#    define FREE(p) (free(p),(p)=NULL)\n\n#endif /* SNIPTYPE__H */\n"
  },
  {
    "path": "include/squashfs/action.h",
    "content": "#ifndef ACTION_H\n#    define ACTION_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2011, 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * action.h\n */\n\n/*\n * Lexical analyser definitions\n */\n#    define TOK_OPEN_BRACKET\t0\n#    define TOK_CLOSE_BRACKET\t1\n#    define TOK_AND\t\t\t2\n#    define TOK_OR\t\t\t3\n#    define TOK_NOT\t\t\t4\n#    define TOK_COMMA\t\t5\n#    define TOK_AT\t\t\t6\n#    define TOK_WHITE_SPACE\t\t7\n#    define TOK_STRING\t\t8\n#    define TOK_EOF\t\t\t9\n\n#    define TOK_TO_STR(OP, S) ({ \\\n\tchar *s; \\\n\tswitch(OP) { \\\n\tcase TOK_EOF: \\\n\t\ts = \"EOF\"; \\\n\t\tbreak; \\\n\tcase TOK_STRING: \\\n\t\ts = S; \\\n\t\tbreak; \\\n\tdefault: \\\n\t\ts = token_table[OP].string; \\\n\t\tbreak; \\\n\t} \\\n\ts; \\\n})\n\nstruct token_entry {\n\tchar *string;\n\tint token;\n\tint size;\n};\n\n/*\n * Expression parser definitions\n */\n#    define OP_TYPE\t\t\t0\n#    define ATOM_TYPE\t\t1\n#    define UNARY_TYPE\t\t2\n\n#    define SYNTAX_ERROR(S, ARGS...) { \\\n\tchar *src = strdup(source); \\\n\tsrc[cur_ptr - source] = '\\0'; \\\n\tfprintf(stderr, \"Failed to parse action \\\"%s\\\"\\n\", source); \\\n\tfprintf(stderr, \"Syntax error: \"S, ##ARGS); \\\n\tfprintf(stderr, \"Got here \\\"%s\\\"\\n\", src); \\\n\tfree(src); \\\n}\n\n#    define TEST_SYNTAX_ERROR(TEST, ARG, S, ARGS...) { \\\n\tchar *src = strdup(source); \\\n\tsrc[cur_ptr - source] = '\\0'; \\\n\tfprintf(stderr, \"Failed to parse action \\\"%s\\\"\\n\", source); \\\n\tfprintf(stderr, \"Syntax error in \\\"%s()\\\", arg %d: \"S, TEST->name, \\\n\t\t\t ARG, ##ARGS); \\\n\tfprintf(stderr, \"Got here \\\"%s\\\"\\n\", src); \\\n\tfree(src); \\\n}\n\nstruct expr;\n\nstruct expr_op {\n\tstruct expr *lhs;\n\tstruct expr *rhs;\n\tint op;\n};\n\nstruct atom {\n\tstruct test_entry *test;\n\tchar **argv;\n\tvoid *data;\n};\n\nstruct unary_op {\n\tstruct expr *expr;\n\tint op;\n};\n\nstruct expr {\n\tint type;\n\tunion {\n\t\tstruct atom atom;\n\t\tstruct expr_op expr_op;\n\t\tstruct unary_op unary_op;\n\t};\n};\n\n/*\n * Test operation definitions\n */\n#    define NUM_EQ\t\t1\n#    define NUM_LESS\t2\n#    define NUM_GREATER\t3\n\nstruct test_number_arg {\n\tlong long size;\n\tint range;\n};\n\nstruct test_range_args {\n\tlong long start;\n\tlong long end;\n};\n\nstruct action;\nstruct action_data;\n\nstruct test_entry {\n\tchar *name;\n\tint args;\n\tint (*fn) (struct atom *, struct action_data *);\n\tint (*parse_args) (struct test_entry *, struct atom *);\n};\n\n/*\n * Type test specific definitions\n */\nstruct type_entry {\n\tint value;\n\tchar type;\n};\n\n/*\n * Action definitions\n */\n#    define FRAGMENT_ACTION 0\n#    define EXCLUDE_ACTION 1\n#    define FRAGMENTS_ACTION 2\n#    define NO_FRAGMENTS_ACTION 3\n#    define ALWAYS_FRAGS_ACTION 4\n#    define NO_ALWAYS_FRAGS_ACTION 5\n#    define COMPRESSED_ACTION 6\n#    define UNCOMPRESSED_ACTION 7\n#    define UID_ACTION 8\n#    define GID_ACTION 9\n#    define GUID_ACTION 10\n#    define MODE_ACTION 11\n#    define EMPTY_ACTION 12\n#    define MOVE_ACTION 13\n\n/*\n * Define what file types each action operates over\n */\n#    define ACTION_DIR S_IFDIR\n#    define ACTION_REG S_IFREG\n#    define ACTION_ALL_LNK (S_IFDIR | S_IFREG | S_IFBLK | S_IFCHR | S_IFSOCK | \\\n\t\t\tS_IFIFO | S_IFLNK)\n#    define ACTION_ALL (S_IFDIR | S_IFREG | S_IFBLK | S_IFCHR | S_IFSOCK | S_IFIFO)\n\nstruct action_entry {\n\tchar *name;\n\tint type;\n\tint args;\n\tint file_types;\n\tint (*parse_args) (struct action_entry *, int, char **, void **);\n\tvoid (*run_action) (struct action *, struct dir_ent *);\n};\n\nstruct action_data {\n\tint depth;\n\tchar *name;\n\tchar *pathname;\n\tchar *subpath;\n\tstruct stat *buf;\n};\n\nstruct action {\n\tint type;\n\tstruct action_entry *action;\n\tint args;\n\tchar **argv;\n\tstruct expr *expr;\n\tvoid *data;\n};\n\n/*\n * Uid/gid action specific definitions\n */\nstruct uid_info {\n\tuid_t uid;\n};\n\nstruct gid_info {\n\tgid_t gid;\n};\n\nstruct guid_info {\n\tuid_t uid;\n\tgid_t gid;\n};\n\n/*\n * Mode action specific definitions\n */\n#    define ACTION_MODE_SET 0\n#    define ACTION_MODE_ADD 1\n#    define ACTION_MODE_REM 2\n#    define ACTION_MODE_OCT 3\n\nstruct mode_data {\n\tstruct mode_data *next;\n\tint operation;\n\tint mode;\n\tunsigned int mask;\n\tchar X;\n};\n\n/*\n * Empty action specific definitions\n */\n#    define EMPTY_ALL 0\n#    define EMPTY_SOURCE 1\n#    define EMPTY_EXCLUDED 2\n\nstruct empty_data {\n\tint val;\n};\n\n/*\n * Move action specific definitions\n */\n#    define ACTION_MOVE_RENAME 1\n#    define ACTION_MOVE_MOVE 2\n\nstruct move_ent {\n\tint ops;\n\tstruct dir_ent *dir_ent;\n\tchar *name;\n\tstruct dir_info *dest;\n\tstruct move_ent *next;\n};\n\n/*\n * External function definitions\n */\nextern int parse_action(char *);\nextern void dump_actions();\nextern void *eval_frag_actions(struct dir_ent *);\nextern void *get_frag_action(void *);\nextern int eval_exclude_actions(char *, char *, char *, struct stat *, int);\nextern void eval_actions(struct dir_ent *);\nextern int eval_empty_actions(struct dir_ent *dir_ent);\nextern void eval_move_actions(struct dir_info *, struct dir_ent *);\nextern void do_move_actions();\nextern int read_bytes(int, void *, int);\nextern int actions();\nextern int move_actions();\nextern int empty_actions();\nextern int read_action_file(char *);\nextern int exclude_actions();\n#endif\n"
  },
  {
    "path": "include/squashfs/caches-queues-lists.h",
    "content": "#ifndef CACHES_QUEUES_LISTS_H\n#    define CACHES_QUEUES_LISTS_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * caches-queues-lists.h\n */\n\n#    define INSERT_LIST(NAME, TYPE) \\\nvoid insert_##NAME##_list(TYPE **list, TYPE *entry) { \\\n\tif(*list) { \\\n\t\tentry->NAME##_next = *list; \\\n\t\tentry->NAME##_prev = (*list)->NAME##_prev; \\\n\t\t(*list)->NAME##_prev->NAME##_next = entry; \\\n\t\t(*list)->NAME##_prev = entry; \\\n\t} else { \\\n\t\t*list = entry; \\\n\t\tentry->NAME##_prev = entry->NAME##_next = entry; \\\n\t} \\\n}\n\n#    define REMOVE_LIST(NAME, TYPE) \\\nvoid remove_##NAME##_list(TYPE **list, TYPE *entry) { \\\n\tif(entry->NAME##_prev == entry && entry->NAME##_next == entry) { \\\n\t\t/* only this entry in the list */ \\\n\t\t*list = NULL; \\\n\t} else if(entry->NAME##_prev != NULL && entry->NAME##_next != NULL) { \\\n\t\t/* more than one entry in the list */ \\\n\t\tentry->NAME##_next->NAME##_prev = entry->NAME##_prev; \\\n\t\tentry->NAME##_prev->NAME##_next = entry->NAME##_next; \\\n\t\tif(*list == entry) \\\n\t\t\t*list = entry->NAME##_next; \\\n\t} \\\n\tentry->NAME##_prev = entry->NAME##_next = NULL; \\\n}\n\n#    define INSERT_HASH_TABLE(NAME, TYPE, HASH_FUNCTION, FIELD, LINK) \\\nvoid insert_##NAME##_hash_table(TYPE *container, struct file_buffer *entry) \\\n{ \\\n\tint hash = HASH_FUNCTION(entry->FIELD); \\\n\\\n\tentry->LINK##_next = container->hash_table[hash]; \\\n\tcontainer->hash_table[hash] = entry; \\\n\tentry->LINK##_prev = NULL; \\\n\tif(entry->LINK##_next) \\\n\t\tentry->LINK##_next->LINK##_prev = entry; \\\n}\n\n#    define REMOVE_HASH_TABLE(NAME, TYPE, HASH_FUNCTION, FIELD, LINK) \\\nvoid remove_##NAME##_hash_table(TYPE *container, struct file_buffer *entry) \\\n{ \\\n\tif(entry->LINK##_prev) \\\n\t\tentry->LINK##_prev->LINK##_next = entry->LINK##_next; \\\n\telse \\\n\t\tcontainer->hash_table[HASH_FUNCTION(entry->FIELD)] = \\\n\t\t\tentry->LINK##_next; \\\n\tif(entry->LINK##_next) \\\n\t\tentry->LINK##_next->LINK##_prev = entry->LINK##_prev; \\\n\\\n\tentry->LINK##_prev = entry->LINK##_next = NULL; \\\n}\n\n#    define HASH_SIZE 65536\n#    define CALCULATE_HASH(n) ((n) & 0xffff)\n\n/* struct describing a cache entry passed between threads */\nstruct file_buffer {\n\tunion {\n\t\tlong long index;\n\t\tlong long sequence;\n\t};\n\tlong long file_size;\n\tunion {\n\t\tlong long block;\n\t\tunsigned short checksum;\n\t};\n\tstruct cache *cache;\n\tunion {\n\t\tstruct file_info *dupl_start;\n\t\tstruct file_buffer *hash_next;\n\t};\n\tunion {\n\t\tint duplicate;\n\t\tstruct file_buffer *hash_prev;\n\t};\n\tunion {\n\t\tstruct {\n\t\t\tstruct file_buffer *free_next;\n\t\t\tstruct file_buffer *free_prev;\n\t\t};\n\t\tstruct {\n\t\t\tstruct file_buffer *seq_next;\n\t\t\tstruct file_buffer *seq_prev;\n\t\t};\n\t};\n\tint size;\n\tint c_byte;\n\tchar used;\n\tchar fragment;\n\tchar error;\n\tchar locked;\n\tchar wait_on_unlock;\n\tchar noD;\n\tchar data[0];\n};\n\n/* struct describing queues used to pass data between threads */\nstruct queue {\n\tint size;\n\tint readp;\n\tint writep;\n\tpthread_mutex_t mutex;\n\tpthread_cond_t empty;\n\tpthread_cond_t full;\n\tvoid **data;\n};\n\n/*\n * struct describing seq_queues used to pass data between the read\n * thread and the deflate and main threads\n */\nstruct seq_queue {\n\tint fragment_count;\n\tint block_count;\n\tstruct file_buffer *hash_table[HASH_SIZE];\n\tpthread_mutex_t mutex;\n\tpthread_cond_t wait;\n};\n\n/* Cache status struct.  Caches are used to keep\n  track of memory buffers passed between different threads */\nstruct cache {\n\tint max_buffers;\n\tint count;\n\tint buffer_size;\n\tint noshrink_lookup;\n\tint first_freelist;\n\tunion {\n\t\tint used;\n\t\tint max_count;\n\t};\n\tpthread_mutex_t mutex;\n\tpthread_cond_t wait_for_free;\n\tpthread_cond_t wait_for_unlock;\n\tstruct file_buffer *free_list;\n\tstruct file_buffer *hash_table[HASH_SIZE];\n};\n\nextern struct queue *queue_init(int);\nextern void queue_put(struct queue *, void *);\nextern void *queue_get(struct queue *);\nextern int queue_empty(struct queue *);\nextern void queue_flush(struct queue *);\nextern void dump_queue(struct queue *);\nextern struct seq_queue *seq_queue_init();\nextern void seq_queue_put(struct seq_queue *, struct file_buffer *);\nextern void dump_seq_queue(struct seq_queue *, int);\nextern struct file_buffer *seq_queue_get(struct seq_queue *);\nextern void seq_queue_flush(struct seq_queue *);\nextern struct cache *cache_init(int, int, int, int);\nextern struct file_buffer *cache_lookup(struct cache *, long long);\nextern struct file_buffer *cache_get(struct cache *, long long);\nextern struct file_buffer *cache_get_nohash(struct cache *);\nextern void cache_hash(struct file_buffer *, long long);\nextern void cache_block_put(struct file_buffer *);\nextern void dump_cache(struct cache *);\nextern struct file_buffer *cache_get_nowait(struct cache *, long long);\nextern struct file_buffer *cache_lookup_nowait(struct cache *, long long, char *);\nextern void cache_wait_unlock(struct file_buffer *);\nextern void cache_unlock(struct file_buffer *);\n\nextern int first_freelist;\n#endif\n"
  },
  {
    "path": "include/squashfs/compressor.h",
    "content": "#ifndef COMPRESSOR_H\n#    define COMPRESSOR_H\n/*\n *\n * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * compressor.h\n */\n\nstruct compressor {\n\tint id;\n\tchar *name;\n\tint supported;\n\tint (*init) (void **, int, int);\n\tint (*compress) (void *, void *, void *, int, int, int *);\n\tint (*uncompress) (void *, void *, int, int, int *);\n\tint (*options) (char **, int);\n\tint (*options_post) (int);\n\tvoid *(*dump_options) (int, int *);\n\tint (*extract_options) (int, void *, int);\n\tint (*check_options) (int, void *, int);\n\tvoid (*display_options) (void *, int);\n\tvoid (*usage) ();\n};\n\nextern struct compressor *lookup_compressor(char *);\nextern struct compressor *lookup_compressor_id(int);\nextern void display_compressors(char *, char *);\nextern void display_compressor_usage(char *);\n\nstatic inline int compressor_init(struct compressor *comp, void **stream, int block_size, int datablock) {\n\tif (comp->init == NULL)\n\t\treturn 0;\n\treturn comp->init(stream, block_size, datablock);\n}\n\nstatic inline int compressor_compress(struct compressor *comp, void *strm, void *dest, void *src, int size, int block_size, int *error) {\n\treturn comp->compress(strm, dest, src, size, block_size, error);\n}\n\nstatic inline int compressor_uncompress(struct compressor *comp, void *dest, void *src, int size, int block_size, int *error) {\n\treturn comp->uncompress(dest, src, size, block_size, error);\n}\n\n/*\n * For the following functions please see the lzo, lz4 or xz\n * compressors for commented examples of how they are used.\n */\nstatic inline int compressor_options(struct compressor *comp, char *argv[], int argc) {\n\tif (comp->options == NULL)\n\t\treturn -1;\n\n\treturn comp->options(argv, argc);\n}\n\nstatic inline int compressor_options_post(struct compressor *comp, int block_size) {\n\tif (comp->options_post == NULL)\n\t\treturn 0;\n\treturn comp->options_post(block_size);\n}\n\nstatic inline void *compressor_dump_options(struct compressor *comp, int block_size, int *size) {\n\tif (comp->dump_options == NULL)\n\t\treturn NULL;\n\treturn comp->dump_options(block_size, size);\n}\n\nstatic inline int compressor_extract_options(struct compressor *comp, int block_size, void *buffer, int size) {\n\tif (comp->extract_options == NULL)\n\t\treturn size ? -1 : 0;\n\treturn comp->extract_options(block_size, buffer, size);\n}\n\nstatic inline int compressor_check_options(struct compressor *comp, int block_size, void *buffer, int size) {\n\tif (comp->check_options == NULL)\n\t\treturn 0;\n\treturn comp->check_options(block_size, buffer, size);\n}\n\nstatic inline void compressor_display_options(struct compressor *comp, void *buffer, int size) {\n\tif (comp->display_options != NULL)\n\t\tcomp->display_options(buffer, size);\n}\n#endif\n"
  },
  {
    "path": "include/squashfs/error.h",
    "content": "#ifndef ERROR_H\n#    define ERROR_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * error.h\n */\n\nextern int exit_on_error;\n\nextern void prep_exit();\nextern void progressbar_error(char *fmt, ...);\nextern void progressbar_info(char *fmt, ...);\n\n#    ifdef SQUASHFS_TRACE\n#        define TRACE(s, args...) \\\n\t\tdo { \\\n\t\t\tprogressbar_info(\"squashfs: \"s, ## args);\\\n\t\t} while(0)\n#    else\n#        define TRACE(s, args...)\n#    endif\n\n#    define INFO(s, args...) \\\n\t\tdo {\\\n\t\t\t if(!silent)\\\n\t\t\t\tprogressbar_info(s, ## args);\\\n\t\t} while(0)\n\n#    define ERROR(s, args...) \\\n\t\tdo {\\\n\t\t\tprogressbar_error(s, ## args); \\\n\t\t} while(0)\n\n#    define ERROR_START(s, args...) \\\n\t\tdo { \\\n\t\t\tdisable_progress_bar(); \\\n\t\t\tfprintf(stderr, s, ## args); \\\n\t\t} while(0)\n\n#    define ERROR_EXIT(s, args...) \\\n\t\tdo {\\\n\t\t\tif (exit_on_error) { \\\n\t\t\t\tfprintf(stderr, \"\\n\"); \\\n\t\t\t\tEXIT_MKSQUASHFS(); \\\n\t\t\t} else { \\\n\t\t\t\tfprintf(stderr, s, ## args); \\\n\t\t\t\tenable_progress_bar(); \\\n\t\t\t} \\\n\t\t} while(0)\n\n#    define EXIT_MKSQUASHFS() \\\n\t\tdo {\\\n\t\t\tprep_exit();\\\n\t\t\texit(1);\\\n\t\t} while(0)\n\n#    define BAD_ERROR(s, args...) \\\n\t\tdo {\\\n\t\t\tprogressbar_error(\"FATAL ERROR:\" s, ##args); \\\n\t\t\tEXIT_MKSQUASHFS();\\\n\t\t} while(0)\n\n#    define EXIT_UNSQUASH(s, args...) BAD_ERROR(s, ##args)\n\n#    define MEM_ERROR() \\\n\tdo {\\\n\t\tprogressbar_error(\"FATAL ERROR: Out of memory (%s)\\n\", \\\n\t\t\t\t\t\t\t\t__func__); \\\n\t\tEXIT_MKSQUASHFS();\\\n\t} while(0)\n#endif\n"
  },
  {
    "path": "include/squashfs/gzip_wrapper.h",
    "content": "#ifndef GZIP_WRAPPER_H\n#    define GZIP_WRAPPER_H\n/*\n * Squashfs\n *\n * Copyright (c) 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * gzip_wrapper.h\n *\n */\n\n#    if !defined(linux) && !defined(__CYGWIN__)\n#        define __BYTE_ORDER BYTE_ORDER\n#        define __BIG_ENDIAN BIG_ENDIAN\n#        define __LITTLE_ENDIAN LITTLE_ENDIAN\n#    else\n#        include <endian.h>\n#    endif\n\n#    if __BYTE_ORDER == __BIG_ENDIAN\nextern unsigned int inswap_le16(unsigned short);\nextern unsigned int inswap_le32(unsigned int);\n\n#        define SQUASHFS_INSWAP_COMP_OPTS(s) { \\\n\t(s)->compression_level = inswap_le32((s)->compression_level); \\\n\t(s)->window_size = inswap_le16((s)->window_size); \\\n\t(s)->strategy = inswap_le16((s)->strategy); \\\n}\n#    else\n#        define SQUASHFS_INSWAP_COMP_OPTS(s)\n#    endif\n\n/* Default compression */\n#    define GZIP_DEFAULT_COMPRESSION_LEVEL 9\n#    define GZIP_DEFAULT_WINDOW_SIZE 15\n\nstruct gzip_comp_opts {\n\tint compression_level;\n\tshort window_size;\n\tshort strategy;\n};\n\nstruct strategy {\n\tchar *name;\n\tint strategy;\n\tint selected;\n};\n\nstruct gzip_strategy {\n\tint strategy;\n\tint length;\n\tvoid *buffer;\n};\n\nstruct gzip_stream {\n\tz_stream stream;\n\tint strategies;\n\tstruct gzip_strategy strategy[0];\n};\n#endif\n"
  },
  {
    "path": "include/squashfs/info.h",
    "content": "#ifndef INFO_H\n#    define INFO_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * info.h\n */\n\nextern void disable_info();\nextern void update_info(struct dir_ent *);\nextern void init_info();\n#endif\n"
  },
  {
    "path": "include/squashfs/lz4_wrapper.h",
    "content": "#ifndef LZ4_WRAPPER_H\n#    define LZ4_WRAPPER_H\n/*\n * Squashfs\n *\n * Copyright (c) 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * lz4_wrapper.h\n *\n */\n\n#    if !defined(linux) && !defined(__CYGWIN__)\n#        define __BYTE_ORDER BYTE_ORDER\n#        define __BIG_ENDIAN BIG_ENDIAN\n#        define __LITTLE_ENDIAN LITTLE_ENDIAN\n#    else\n#        include <endian.h>\n#    endif\n\n#    if __BYTE_ORDER == __BIG_ENDIAN\nextern unsigned int inswap_le32(unsigned int);\n\n#        define SQUASHFS_INSWAP_COMP_OPTS(s) { \\\n\t(s)->version = inswap_le32((s)->version); \\\n\t(s)->flags = inswap_le32((s)->flags); \\\n}\n#    else\n#        define SQUASHFS_INSWAP_COMP_OPTS(s)\n#    endif\n\n/*\n * Define the various stream formats recognised.\n * Currently omly legacy stream format is supported by the\n * kernel\n */\n#    define LZ4_LEGACY\t1\n#    define LZ4_FLAGS_MASK\t1\n\n/* Define the compression flags recognised. */\n#    define LZ4_HC\t\t1\n\nstruct lz4_comp_opts {\n\tint version;\n\tint flags;\n};\n#endif\n"
  },
  {
    "path": "include/squashfs/lzo_wrapper.h",
    "content": "#ifndef LZO_WRAPPER_H\n#    define LZO_WRAPPER_H\n/*\n * Squashfs\n *\n * Copyright (c) 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * lzo_wrapper.h\n *\n */\n\n#    if !defined(linux) && !defined(__CYGWIN__)\n#        define __BYTE_ORDER BYTE_ORDER\n#        define __BIG_ENDIAN BIG_ENDIAN\n#        define __LITTLE_ENDIAN LITTLE_ENDIAN\n#    else\n#        include <endian.h>\n#    endif\n\n#    if __BYTE_ORDER == __BIG_ENDIAN\nextern unsigned int inswap_le32(unsigned int);\n\n#        define SQUASHFS_INSWAP_COMP_OPTS(s) { \\\n\t(s)->algorithm = inswap_le32((s)->algorithm); \\\n\t(s)->compression_level = inswap_le32((s)->compression_level); \\\n}\n#    else\n#        define SQUASHFS_INSWAP_COMP_OPTS(s)\n#    endif\n\n/* Define the compression flags recognised. */\n#    define SQUASHFS_LZO1X_1\t0\n#    define SQUASHFS_LZO1X_1_11\t1\n#    define SQUASHFS_LZO1X_1_12\t2\n#    define SQUASHFS_LZO1X_1_15\t3\n#    define SQUASHFS_LZO1X_999\t4\n\n/* Default compression level used by SQUASHFS_LZO1X_999 */\n#    define SQUASHFS_LZO1X_999_COMP_DEFAULT\t8\n\nstruct lzo_comp_opts {\n\tint algorithm;\n\tint compression_level;\n};\n\nstruct lzo_algorithm {\n\tchar *name;\n\tint size;\n\tint (*compress) (const lzo_bytep, lzo_uint, lzo_bytep, lzo_uintp, lzo_voidp);\n};\n\nstruct lzo_stream {\n\tvoid *workspace;\n\tvoid *buffer;\n};\n\n#    define LZO_MAX_EXPANSION(size)\t(size + (size / 16) + 64 + 3)\n\nint lzo1x_999_wrapper(const lzo_bytep, lzo_uint, lzo_bytep, lzo_uintp, lzo_voidp);\n\n#endif\n"
  },
  {
    "path": "include/squashfs/mksquashfs.h",
    "content": "#ifndef MKSQUASHFS_H\n#    define MKSQUASHFS_H\n/*\n * Squashfs\n *\n * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011\n * 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * mksquashfs.h\n *\n */\n\nstruct dir_info {\n\tchar *pathname;\n\tchar *subpath;\n\tunsigned int count;\n\tunsigned int directory_count;\n\tint depth;\n\tunsigned int excluded;\n\tchar dir_is_ldir;\n\tstruct dir_ent *dir_ent;\n\tstruct dir_ent *list;\n\tDIR *linuxdir;\n};\n\nstruct dir_ent {\n\tchar *name;\n\tchar *source_name;\n\tchar *nonstandard_pathname;\n\tstruct inode_info *inode;\n\tstruct dir_info *dir;\n\tstruct dir_info *our_dir;\n\tstruct dir_ent *next;\n};\n\nstruct inode_info {\n\tstruct stat buf;\n\tstruct inode_info *next;\n\tsquashfs_inode inode;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tint pseudo_id;\n\tchar type;\n\tchar read;\n\tchar root_entry;\n\tchar pseudo_file;\n\tchar no_fragments;\n\tchar always_use_fragments;\n\tchar noD;\n\tchar noF;\n};\n\n/* in memory file info */\nstruct file_info {\n\tlong long file_size;\n\tlong long bytes;\n\tlong long start;\n\tunsigned int *block_list;\n\tstruct file_info *next;\n\tstruct fragment *fragment;\n\tunsigned short checksum;\n\tunsigned short fragment_checksum;\n\tchar have_frag_checksum;\n\tchar have_checksum;\n};\n\n/* fragment block data structures */\nstruct fragment {\n\tunsigned int index;\n\tint offset;\n\tint size;\n};\n\n/* in memory uid tables */\n#    define ID_ENTRIES 256\n#    define ID_HASH(id) (id & (ID_ENTRIES - 1))\n#    define ISA_UID 1\n#    define ISA_GID 2\n\nstruct id {\n\tunsigned int id;\n\tint index;\n\tchar flags;\n\tstruct id *next;\n};\n\n/* fragment to file mapping used when appending */\nstruct append_file {\n\tstruct file_info *file;\n\tstruct append_file *next;\n};\n\n#    define PSEUDO_FILE_OTHER\t1\n#    define PSEUDO_FILE_PROCESS\t2\n\n#    define IS_PSEUDO(a)\t\t((a)->pseudo_file)\n#    define IS_PSEUDO_PROCESS(a)\t((a)->pseudo_file & PSEUDO_FILE_PROCESS)\n#    define IS_PSEUDO_OTHER(a)\t((a)->pseudo_file & PSEUDO_FILE_OTHER)\n\n/*\n * Amount of physical memory to use by default, and the default queue\n * ratios\n */\n#    define SQUASHFS_TAKE 4\n#    define SQUASHFS_READQ_MEM 4\n#    define SQUASHFS_BWRITEQ_MEM 4\n#    define SQUASHFS_FWRITEQ_MEM 4\n\n/*\n * Lowest amount of physical memory considered viable for Mksquashfs\n * to run in Mbytes\n */\n#    define SQUASHFS_LOWMEM 64\n\n/* offset of data in compressed metadata blocks (allowing room for\n * compressed size */\n#    define BLOCK_OFFSET 2\n\nextern struct cache *reader_buffer, *fragment_buffer, *reserve_cache;\nstruct cache *bwriter_buffer, *fwriter_buffer;\nextern struct queue *to_reader, *to_deflate, *to_writer, *from_writer, *to_frag, *locked_fragment, *to_process_frag;\nextern struct append_file **file_mapping;\nextern struct seq_queue *to_main;\nextern pthread_mutex_t fragment_mutex, dup_mutex;\nextern struct squashfs_fragment_entry *fragment_table;\nextern struct compressor *comp;\nextern int block_size;\nextern struct file_info *dupl[];\nextern int read_fs_bytes(int, long long, int, void *);\nextern void add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int);\nextern struct id *create_id(unsigned int);\nextern unsigned int get_uid(unsigned int);\nextern unsigned int get_guid(unsigned int);\nextern int read_bytes(int, void *, int);\nextern unsigned short get_checksum_mem(char *, int);\n#endif\n"
  },
  {
    "path": "include/squashfs/process_fragments.h",
    "content": "#ifndef PROCESS_FRAGMENTS_H\n#    define PROCESS_FRAGMENTS_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * process_fragments.h\n */\n\n#    define DUP_HASH(a) (a & 0xffff)\n\nextern void *frag_thrd(void *);\n#endif\n"
  },
  {
    "path": "include/squashfs/progressbar.h",
    "content": "#ifndef PROGRESSBAR_H\n#    define PROGRESSBAR_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * progressbar.h\n */\n\nextern void inc_progress_bar();\nextern void dec_progress_bar(int count);\nextern void progress_bar_size(int count);\nextern void enable_progress_bar();\nextern void disable_progress_bar();\nextern void init_progress_bar();\nextern void set_progressbar_state(int);\n#endif\n"
  },
  {
    "path": "include/squashfs/pseudo.h",
    "content": "#ifndef PSEUDO_H\n#    define PSEUDO_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2009, 2010, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * pseudo.h\n */\nstruct pseudo_dev {\n\tchar type;\n\tunsigned int mode;\n\tunsigned int uid;\n\tunsigned int gid;\n\tunsigned int major;\n\tunsigned int minor;\n\tint pseudo_id;\n\tchar *command;\n};\n\nstruct pseudo_entry {\n\tchar *name;\n\tchar *pathname;\n\tstruct pseudo *pseudo;\n\tstruct pseudo_dev *dev;\n};\n\nstruct pseudo {\n\tint names;\n\tint count;\n\tstruct pseudo_entry *name;\n};\n\nextern int read_pseudo_def(char *);\nextern int read_pseudo_file(char *);\nextern struct pseudo *pseudo_subdir(char *, struct pseudo *);\nextern struct pseudo_entry *pseudo_readdir(struct pseudo *);\nextern struct pseudo_dev *get_pseudo_file(int);\nextern int pseudo_exec_file(struct pseudo_dev *, int *);\nextern struct pseudo *get_pseudo();\nextern void dump_pseudos();\n#endif\n"
  },
  {
    "path": "include/squashfs/read_fs.h",
    "content": "#ifndef READ_FS_H\n#    define READ_FS_H\n/*\n * Squashfs\n *\n * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * read_fs.h\n *\n */\nextern struct compressor *read_super(int, struct squashfs_super_block *, char *);\nextern long long read_filesystem(char *, int, struct squashfs_super_block *, char **, char **, char **, char **, unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *, int *, int *, int *, int *, int *, int *, long long *, unsigned int *, unsigned int *, unsigned int *, unsigned int *, void (push_directory_entry) (char *, squashfs_inode, int, int), struct squashfs_fragment_entry **, squashfs_inode **);\n#endif\n"
  },
  {
    "path": "include/squashfs/restore.h",
    "content": "#ifndef RESTORE_H\n#    define RESTORE_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * restore.h\n */\n\nextern pthread_t *init_restore_thread();\n#endif\n"
  },
  {
    "path": "include/squashfs/sort.h",
    "content": "#ifndef SORT_H\n#    define SORT_H\n\n/*\n * Squashfs\n *\n * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * sort.h\n */\n\nstruct priority_entry {\n\tstruct dir_ent *dir;\n\tstruct priority_entry *next;\n};\n\nextern int read_sort_file(char *, int, char *[]);\nextern void sort_files_and_write(struct dir_info *);\nextern void generate_file_priorities(struct dir_info *, int priority, struct stat *);\nextern struct priority_entry *priority_list[65536];\n#endif\n"
  },
  {
    "path": "include/squashfs/squashfs_compat.h",
    "content": "#ifndef SQUASHFS_COMPAT\n#    define SQUASHFS_COMPAT\n/*\n * Squashfs\n *\n * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * squashfs_compat.h\n */\n\n/*\n * definitions for structures on disk - layout 3.x\n */\n\n#    define SQUASHFS_CHECK\t\t\t2\n#    define SQUASHFS_CHECK_DATA(flags)\t\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_CHECK)\n\n/* Max number of uids and gids */\n#    define SQUASHFS_UIDS\t\t\t256\n#    define SQUASHFS_GUIDS\t\t\t255\n\nstruct squashfs_super_block_3 {\n\tunsigned int s_magic;\n\tunsigned int inodes;\n\tunsigned int bytes_used_2;\n\tunsigned int uid_start_2;\n\tunsigned int guid_start_2;\n\tunsigned int inode_table_start_2;\n\tunsigned int directory_table_start_2;\n\tunsigned int s_major:16;\n\tunsigned int s_minor:16;\n\tunsigned int block_size_1:16;\n\tunsigned int block_log:16;\n\tunsigned int flags:8;\n\tunsigned int no_uids:8;\n\tunsigned int no_guids:8;\n\tint mkfs_time /* time of filesystem creation */ ;\n\tsquashfs_inode root_inode;\n\tunsigned int block_size;\n\tunsigned int fragments;\n\tunsigned int fragment_table_start_2;\n\tlong long bytes_used;\n\tlong long uid_start;\n\tlong long guid_start;\n\tlong long inode_table_start;\n\tlong long directory_table_start;\n\tlong long fragment_table_start;\n\tlong long lookup_table_start;\n} __attribute__ ((packed));\n\nstruct squashfs_dir_index_3 {\n\tunsigned int index;\n\tunsigned int start_block;\n\tunsigned char size;\n\tunsigned char name[0];\n} __attribute__ ((packed));\n\nstruct squashfs_base_inode_header_3 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\n\tunsigned int uid:8;\n\tunsigned int guid:8;\n\tint mtime;\n\tunsigned int inode_number;\n} __attribute__ ((packed));\n\nstruct squashfs_ipc_inode_header_3 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\n\tunsigned int uid:8;\n\tunsigned int guid:8;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n} __attribute__ ((packed));\n\nstruct squashfs_dev_inode_header_3 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\n\tunsigned int uid:8;\n\tunsigned int guid:8;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tunsigned short rdev;\n} __attribute__ ((packed));\n\nstruct squashfs_symlink_inode_header_3 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\n\tunsigned int uid:8;\n\tunsigned int guid:8;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tunsigned short symlink_size;\n\tchar symlink[0];\n} __attribute__ ((packed));\n\nstruct squashfs_reg_inode_header_3 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\n\tunsigned int uid:8;\n\tunsigned int guid:8;\n\tint mtime;\n\tunsigned int inode_number;\n\tsquashfs_block start_block;\n\tunsigned int fragment;\n\tunsigned int offset;\n\tunsigned int file_size;\n\tunsigned short block_list[0];\n} __attribute__ ((packed));\n\nstruct squashfs_lreg_inode_header_3 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\n\tunsigned int uid:8;\n\tunsigned int guid:8;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tsquashfs_block start_block;\n\tunsigned int fragment;\n\tunsigned int offset;\n\tlong long file_size;\n\tunsigned short block_list[0];\n} __attribute__ ((packed));\n\nstruct squashfs_dir_inode_header_3 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\n\tunsigned int uid:8;\n\tunsigned int guid:8;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tunsigned int file_size:19;\n\tunsigned int offset:13;\n\tunsigned int start_block;\n\tunsigned int parent_inode;\n} __attribute__ ((packed));\n\nstruct squashfs_ldir_inode_header_3 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\n\tunsigned int uid:8;\n\tunsigned int guid:8;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tunsigned int file_size:27;\n\tunsigned int offset:13;\n\tunsigned int start_block;\n\tunsigned int i_count:16;\n\tunsigned int parent_inode;\n\tstruct squashfs_dir_index_3 index[0];\n} __attribute__ ((packed));\n\nunion squashfs_inode_header_3 {\n\tstruct squashfs_base_inode_header_3 base;\n\tstruct squashfs_dev_inode_header_3 dev;\n\tstruct squashfs_symlink_inode_header_3 symlink;\n\tstruct squashfs_reg_inode_header_3 reg;\n\tstruct squashfs_lreg_inode_header_3 lreg;\n\tstruct squashfs_dir_inode_header_3 dir;\n\tstruct squashfs_ldir_inode_header_3 ldir;\n\tstruct squashfs_ipc_inode_header_3 ipc;\n};\n\nstruct squashfs_dir_entry_3 {\n\tunsigned int offset:13;\n\tunsigned int type:3;\n\tunsigned int size:8;\n\tint inode_number:16;\n\tchar name[0];\n} __attribute__ ((packed));\n\nstruct squashfs_dir_header_3 {\n\tunsigned int count:8;\n\tunsigned int start_block;\n\tunsigned int inode_number;\n} __attribute__ ((packed));\n\nstruct squashfs_fragment_entry_3 {\n\tlong long start_block;\n\tunsigned int size;\n\tunsigned int pending;\n} __attribute__ ((packed));\n\ntypedef struct squashfs_super_block_3 squashfs_super_block_3;\ntypedef struct squashfs_dir_index_3 squashfs_dir_index_3;\ntypedef struct squashfs_base_inode_header_3 squashfs_base_inode_header_3;\ntypedef struct squashfs_ipc_inode_header_3 squashfs_ipc_inode_header_3;\ntypedef struct squashfs_dev_inode_header_3 squashfs_dev_inode_header_3;\ntypedef struct squashfs_symlink_inode_header_3 squashfs_symlink_inode_header_3;\ntypedef struct squashfs_reg_inode_header_3 squashfs_reg_inode_header_3;\ntypedef struct squashfs_lreg_inode_header_3 squashfs_lreg_inode_header_3;\ntypedef struct squashfs_dir_inode_header_3 squashfs_dir_inode_header_3;\ntypedef struct squashfs_ldir_inode_header_3 squashfs_ldir_inode_header_3;\ntypedef struct squashfs_dir_entry_3 squashfs_dir_entry_3;\ntypedef struct squashfs_dir_header_3 squashfs_dir_header_3;\ntypedef struct squashfs_fragment_entry_3 squashfs_fragment_entry_3;\n\n/*\n * macros to convert each packed bitfield structure from little endian to big\n * endian and vice versa.  These are needed when creating or using a filesystem\n * on a machine with different byte ordering to the target architecture.\n *\n */\n\n#    define SQUASHFS_SWAP_START \\\n\tint bits;\\\n\tint b_pos;\\\n\tunsigned long long val;\\\n\tunsigned char *s;\\\n\tunsigned char *d;\n\n#    define SQUASHFS_SWAP_SUPER_BLOCK_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block_3));\\\n\tSQUASHFS_SWAP((s)->s_magic, d, 0, 32);\\\n\tSQUASHFS_SWAP((s)->inodes, d, 32, 32);\\\n\tSQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\\\n\tSQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\\\n\tSQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\\\n\tSQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\\\n\tSQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\\\n\tSQUASHFS_SWAP((s)->s_major, d, 224, 16);\\\n\tSQUASHFS_SWAP((s)->s_minor, d, 240, 16);\\\n\tSQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\\\n\tSQUASHFS_SWAP((s)->block_log, d, 272, 16);\\\n\tSQUASHFS_SWAP((s)->flags, d, 288, 8);\\\n\tSQUASHFS_SWAP((s)->no_uids, d, 296, 8);\\\n\tSQUASHFS_SWAP((s)->no_guids, d, 304, 8);\\\n\tSQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\\\n\tSQUASHFS_SWAP((s)->root_inode, d, 344, 64);\\\n\tSQUASHFS_SWAP((s)->block_size, d, 408, 32);\\\n\tSQUASHFS_SWAP((s)->fragments, d, 440, 32);\\\n\tSQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\\\n\tSQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\\\n\tSQUASHFS_SWAP((s)->uid_start, d, 568, 64);\\\n\tSQUASHFS_SWAP((s)->guid_start, d, 632, 64);\\\n\tSQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\\\n\tSQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\\\n\tSQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\\\n\tSQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\\\n}\n\n#    define SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\\\n\tSQUASHFS_MEMSET(s, d, n);\\\n\tSQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\\n\tSQUASHFS_SWAP((s)->mode, d, 4, 12);\\\n\tSQUASHFS_SWAP((s)->uid, d, 16, 8);\\\n\tSQUASHFS_SWAP((s)->guid, d, 24, 8);\\\n\tSQUASHFS_SWAP((s)->mtime, d, 32, 32);\\\n\tSQUASHFS_SWAP((s)->inode_number, d, 64, 32);\n\n#    define SQUASHFS_SWAP_BASE_INODE_HEADER_3(s, d, n) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\\\n}\n\n#    define SQUASHFS_SWAP_IPC_INODE_HEADER_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \\\n\t\t\tsizeof(struct squashfs_ipc_inode_header_3))\\\n\tSQUASHFS_SWAP((s)->nlink, d, 96, 32);\\\n}\n\n#    define SQUASHFS_SWAP_DEV_INODE_HEADER_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \\\n\t\t\tsizeof(struct squashfs_dev_inode_header_3)); \\\n\tSQUASHFS_SWAP((s)->nlink, d, 96, 32);\\\n\tSQUASHFS_SWAP((s)->rdev, d, 128, 16);\\\n}\n\n#    define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \\\n\t\t\tsizeof(struct squashfs_symlink_inode_header_3));\\\n\tSQUASHFS_SWAP((s)->nlink, d, 96, 32);\\\n\tSQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\\\n}\n\n#    define SQUASHFS_SWAP_REG_INODE_HEADER_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \\\n\t\t\tsizeof(struct squashfs_reg_inode_header_3));\\\n\tSQUASHFS_SWAP((s)->start_block, d, 96, 64);\\\n\tSQUASHFS_SWAP((s)->fragment, d, 160, 32);\\\n\tSQUASHFS_SWAP((s)->offset, d, 192, 32);\\\n\tSQUASHFS_SWAP((s)->file_size, d, 224, 32);\\\n}\n\n#    define SQUASHFS_SWAP_LREG_INODE_HEADER_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \\\n\t\t\tsizeof(struct squashfs_lreg_inode_header_3));\\\n\tSQUASHFS_SWAP((s)->nlink, d, 96, 32);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 128, 64);\\\n\tSQUASHFS_SWAP((s)->fragment, d, 192, 32);\\\n\tSQUASHFS_SWAP((s)->offset, d, 224, 32);\\\n\tSQUASHFS_SWAP((s)->file_size, d, 256, 64);\\\n}\n\n#    define SQUASHFS_SWAP_DIR_INODE_HEADER_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \\\n\t\t\tsizeof(struct squashfs_dir_inode_header_3));\\\n\tSQUASHFS_SWAP((s)->nlink, d, 96, 32);\\\n\tSQUASHFS_SWAP((s)->file_size, d, 128, 19);\\\n\tSQUASHFS_SWAP((s)->offset, d, 147, 13);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 160, 32);\\\n\tSQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\\\n}\n\n#    define SQUASHFS_SWAP_LDIR_INODE_HEADER_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \\\n\t\t\tsizeof(struct squashfs_ldir_inode_header_3));\\\n\tSQUASHFS_SWAP((s)->nlink, d, 96, 32);\\\n\tSQUASHFS_SWAP((s)->file_size, d, 128, 27);\\\n\tSQUASHFS_SWAP((s)->offset, d, 155, 13);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 168, 32);\\\n\tSQUASHFS_SWAP((s)->i_count, d, 200, 16);\\\n\tSQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\\\n}\n\n#    define SQUASHFS_SWAP_DIR_INDEX_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_3));\\\n\tSQUASHFS_SWAP((s)->index, d, 0, 32);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 32, 32);\\\n\tSQUASHFS_SWAP((s)->size, d, 64, 8);\\\n}\n\n#    define SQUASHFS_SWAP_DIR_HEADER_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_3));\\\n\tSQUASHFS_SWAP((s)->count, d, 0, 8);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 8, 32);\\\n\tSQUASHFS_SWAP((s)->inode_number, d, 40, 32);\\\n}\n\n#    define SQUASHFS_SWAP_DIR_ENTRY_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_3));\\\n\tSQUASHFS_SWAP((s)->offset, d, 0, 13);\\\n\tSQUASHFS_SWAP((s)->type, d, 13, 3);\\\n\tSQUASHFS_SWAP((s)->size, d, 16, 8);\\\n\tSQUASHFS_SWAP((s)->inode_number, d, 24, 16);\\\n}\n\n#    define SQUASHFS_SWAP_INODE_T_3(s, d) SQUASHFS_SWAP_LONG_LONGS_3(s, d, 1)\n\n#    define SQUASHFS_SWAP_SHORTS_3(s, d, n) {\\\n\tint entry;\\\n\tint bit_position;\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, n * 2);\\\n\tfor(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\\n\t\t\t16)\\\n\t\tSQUASHFS_SWAP(s[entry], d, bit_position, 16);\\\n}\n\n#    define SQUASHFS_SWAP_INTS_3(s, d, n) {\\\n\tint entry;\\\n\tint bit_position;\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, n * 4);\\\n\tfor(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\\n\t\t\t32)\\\n\t\tSQUASHFS_SWAP(s[entry], d, bit_position, 32);\\\n}\n\n#    define SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) {\\\n\tint entry;\\\n\tint bit_position;\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, n * 8);\\\n\tfor(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\\n\t\t\t64)\\\n\t\tSQUASHFS_SWAP(s[entry], d, bit_position, 64);\\\n}\n\n#    define SQUASHFS_SWAP_DATA(s, d, n, bits) {\\\n\tint entry;\\\n\tint bit_position;\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, n * bits / 8);\\\n\tfor(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\\n\t\t\tbits)\\\n\t\tSQUASHFS_SWAP(s[entry], d, bit_position, bits);\\\n}\n\n#    define SQUASHFS_SWAP_FRAGMENT_INDEXES_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n)\n#    define SQUASHFS_SWAP_LOOKUP_BLOCKS_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n)\n\n#    define SQUASHFS_SWAP_FRAGMENT_ENTRY_3(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_3));\\\n\tSQUASHFS_SWAP((s)->start_block, d, 0, 64);\\\n\tSQUASHFS_SWAP((s)->size, d, 64, 32);\\\n}\n\n/* fragment and fragment table defines */\n#    define SQUASHFS_FRAGMENT_BYTES_3(A)\t((A) * sizeof(struct squashfs_fragment_entry_3))\n\n#    define SQUASHFS_FRAGMENT_INDEX_3(A)\t(SQUASHFS_FRAGMENT_BYTES_3(A) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_FRAGMENT_INDEX_OFFSET_3(A)\t(SQUASHFS_FRAGMENT_BYTES_3(A) % \\\n\t\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_FRAGMENT_INDEXES_3(A)\t((SQUASHFS_FRAGMENT_BYTES_3(A) + \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE - 1) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_FRAGMENT_INDEX_BYTES_3(A)\t(SQUASHFS_FRAGMENT_INDEXES_3(A) *\\\n\t\t\t\t\t\tsizeof(long long))\n\n/*\n * definitions for structures on disk - layout 1.x\n */\n#    define SQUASHFS_TYPES\t\t\t5\n#    define SQUASHFS_IPC_TYPE\t\t0\n\nstruct squashfs_base_inode_header_1 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:4;\t\t\t/* index into uid table */\n\tunsigned int guid:4;\t\t/* index into guid table */\n} __attribute__ ((packed));\n\nstruct squashfs_ipc_inode_header_1 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:4;\t\t\t/* index into uid table */\n\tunsigned int guid:4;\t\t/* index into guid table */\n\tunsigned int type:4;\n\tunsigned int offset:4;\n} __attribute__ ((packed));\n\nstruct squashfs_dev_inode_header_1 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:4;\t\t\t/* index into uid table */\n\tunsigned int guid:4;\t\t/* index into guid table */\n\tunsigned short rdev;\n} __attribute__ ((packed));\n\nstruct squashfs_symlink_inode_header_1 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:4;\t\t\t/* index into uid table */\n\tunsigned int guid:4;\t\t/* index into guid table */\n\tunsigned short symlink_size;\n\tchar symlink[0];\n} __attribute__ ((packed));\n\nstruct squashfs_reg_inode_header_1 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:4;\t\t\t/* index into uid table */\n\tunsigned int guid:4;\t\t/* index into guid table */\n\tint mtime;\n\tunsigned int start_block;\n\tunsigned int file_size:32;\n\tunsigned short block_list[0];\n} __attribute__ ((packed));\n\nstruct squashfs_dir_inode_header_1 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:4;\t\t\t/* index into uid table */\n\tunsigned int guid:4;\t\t/* index into guid table */\n\tunsigned int file_size:19;\n\tunsigned int offset:13;\n\tint mtime;\n\tunsigned int start_block:24;\n} __attribute__ ((packed));\n\nunion squashfs_inode_header_1 {\n\tstruct squashfs_base_inode_header_1 base;\n\tstruct squashfs_dev_inode_header_1 dev;\n\tstruct squashfs_symlink_inode_header_1 symlink;\n\tstruct squashfs_reg_inode_header_1 reg;\n\tstruct squashfs_dir_inode_header_1 dir;\n\tstruct squashfs_ipc_inode_header_1 ipc;\n};\n\ntypedef struct squashfs_dir_index_1 squashfs_dir_index_1;\ntypedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1;\ntypedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1;\ntypedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1;\ntypedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1;\ntypedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1;\ntypedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1;\n\n#    define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \\\n\tSQUASHFS_MEMSET(s, d, n);\\\n\tSQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\\n\tSQUASHFS_SWAP((s)->mode, d, 4, 12);\\\n\tSQUASHFS_SWAP((s)->uid, d, 16, 4);\\\n\tSQUASHFS_SWAP((s)->guid, d, 20, 4);\n\n#    define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\\\n}\n\n#    define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\\n\t\t\tsizeof(struct squashfs_ipc_inode_header_1));\\\n\tSQUASHFS_SWAP((s)->type, d, 24, 4);\\\n\tSQUASHFS_SWAP((s)->offset, d, 28, 4);\\\n}\n\n#    define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\\n\t\t\tsizeof(struct squashfs_dev_inode_header_1));\\\n\tSQUASHFS_SWAP((s)->rdev, d, 24, 16);\\\n}\n\n#    define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\\n\t\t\tsizeof(struct squashfs_symlink_inode_header_1));\\\n\tSQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\\\n}\n\n#    define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\\n\t\t\tsizeof(struct squashfs_reg_inode_header_1));\\\n\tSQUASHFS_SWAP((s)->mtime, d, 24, 32);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 56, 32);\\\n\tSQUASHFS_SWAP((s)->file_size, d, 88, 32);\\\n}\n\n#    define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\\n\t\t\tsizeof(struct squashfs_dir_inode_header_1));\\\n\tSQUASHFS_SWAP((s)->file_size, d, 24, 19);\\\n\tSQUASHFS_SWAP((s)->offset, d, 43, 13);\\\n\tSQUASHFS_SWAP((s)->mtime, d, 56, 32);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 88, 24);\\\n}\n\n/*\n * definitions for structures on disk - layout 2.x\n */\nstruct squashfs_dir_index_2 {\n\tunsigned int index:27;\n\tunsigned int start_block:29;\n\tunsigned char size;\n\tunsigned char name[0];\n} __attribute__ ((packed));\n\nstruct squashfs_base_inode_header_2 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:8;\t\t\t/* index into uid table */\n\tunsigned int guid:8;\t\t/* index into guid table */\n} __attribute__ ((packed));\n\nstruct squashfs_ipc_inode_header_2 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:8;\t\t\t/* index into uid table */\n\tunsigned int guid:8;\t\t/* index into guid table */\n} __attribute__ ((packed));\n\nstruct squashfs_dev_inode_header_2 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:8;\t\t\t/* index into uid table */\n\tunsigned int guid:8;\t\t/* index into guid table */\n\tunsigned short rdev;\n} __attribute__ ((packed));\n\nstruct squashfs_symlink_inode_header_2 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:8;\t\t\t/* index into uid table */\n\tunsigned int guid:8;\t\t/* index into guid table */\n\tunsigned short symlink_size;\n\tchar symlink[0];\n} __attribute__ ((packed));\n\nstruct squashfs_reg_inode_header_2 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:8;\t\t\t/* index into uid table */\n\tunsigned int guid:8;\t\t/* index into guid table */\n\tint mtime;\n\tunsigned int start_block;\n\tunsigned int fragment;\n\tunsigned int offset;\n\tunsigned int file_size:32;\n\tunsigned short block_list[0];\n} __attribute__ ((packed));\n\nstruct squashfs_dir_inode_header_2 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:8;\t\t\t/* index into uid table */\n\tunsigned int guid:8;\t\t/* index into guid table */\n\tunsigned int file_size:19;\n\tunsigned int offset:13;\n\tint mtime;\n\tunsigned int start_block:24;\n} __attribute__ ((packed));\n\nstruct squashfs_ldir_inode_header_2 {\n\tunsigned int inode_type:4;\n\tunsigned int mode:12;\t\t/* protection */\n\tunsigned int uid:8;\t\t\t/* index into uid table */\n\tunsigned int guid:8;\t\t/* index into guid table */\n\tunsigned int file_size:27;\n\tunsigned int offset:13;\n\tint mtime;\n\tunsigned int start_block:24;\n\tunsigned int i_count:16;\n\tstruct squashfs_dir_index_2 index[0];\n} __attribute__ ((packed));\n\nunion squashfs_inode_header_2 {\n\tstruct squashfs_base_inode_header_2 base;\n\tstruct squashfs_dev_inode_header_2 dev;\n\tstruct squashfs_symlink_inode_header_2 symlink;\n\tstruct squashfs_reg_inode_header_2 reg;\n\tstruct squashfs_dir_inode_header_2 dir;\n\tstruct squashfs_ldir_inode_header_2 ldir;\n\tstruct squashfs_ipc_inode_header_2 ipc;\n};\n\nstruct squashfs_dir_header_2 {\n\tunsigned int count:8;\n\tunsigned int start_block:24;\n} __attribute__ ((packed));\n\nstruct squashfs_dir_entry_2 {\n\tunsigned int offset:13;\n\tunsigned int type:3;\n\tunsigned int size:8;\n\tchar name[0];\n} __attribute__ ((packed));\n\nstruct squashfs_fragment_entry_2 {\n\tunsigned int start_block;\n\tunsigned int size;\n} __attribute__ ((packed));\n\ntypedef struct squashfs_dir_index_2 squashfs_dir_index_2;\ntypedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2;\ntypedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2;\ntypedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2;\ntypedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2;\ntypedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2;\ntypedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2;\ntypedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2;\ntypedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2;\ntypedef struct squashfs_dir_entry_2 squashfs_dir_entry_2;\ntypedef struct squashfs_dir_header_2 squashfs_dir_header_2;\ntypedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2;\n\n#    define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\\\n\tSQUASHFS_MEMSET(s, d, n);\\\n\tSQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\\n\tSQUASHFS_SWAP((s)->mode, d, 4, 12);\\\n\tSQUASHFS_SWAP((s)->uid, d, 16, 8);\\\n\tSQUASHFS_SWAP((s)->guid, d, 24, 8);\\\n\n#    define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\\\n}\n\n#    define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \\\n\tSQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))\n\n#    define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\\n\t\t\tsizeof(struct squashfs_dev_inode_header_2)); \\\n\tSQUASHFS_SWAP((s)->rdev, d, 32, 16);\\\n}\n\n#    define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\\n\t\t\tsizeof(struct squashfs_symlink_inode_header_2));\\\n\tSQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\\\n}\n\n#    define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\\n\t\t\tsizeof(struct squashfs_reg_inode_header_2));\\\n\tSQUASHFS_SWAP((s)->mtime, d, 32, 32);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 64, 32);\\\n\tSQUASHFS_SWAP((s)->fragment, d, 96, 32);\\\n\tSQUASHFS_SWAP((s)->offset, d, 128, 32);\\\n\tSQUASHFS_SWAP((s)->file_size, d, 160, 32);\\\n}\n\n#    define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\\n\t\t\tsizeof(struct squashfs_dir_inode_header_2));\\\n\tSQUASHFS_SWAP((s)->file_size, d, 32, 19);\\\n\tSQUASHFS_SWAP((s)->offset, d, 51, 13);\\\n\tSQUASHFS_SWAP((s)->mtime, d, 64, 32);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 96, 24);\\\n}\n\n#    define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\\n\t\t\tsizeof(struct squashfs_ldir_inode_header_2));\\\n\tSQUASHFS_SWAP((s)->file_size, d, 32, 27);\\\n\tSQUASHFS_SWAP((s)->offset, d, 59, 13);\\\n\tSQUASHFS_SWAP((s)->mtime, d, 72, 32);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 104, 24);\\\n\tSQUASHFS_SWAP((s)->i_count, d, 128, 16);\\\n}\n\n#    define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\\\n\tSQUASHFS_SWAP((s)->index, d, 0, 27);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 27, 29);\\\n\tSQUASHFS_SWAP((s)->size, d, 56, 8);\\\n}\n#    define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\\\n\tSQUASHFS_SWAP((s)->count, d, 0, 8);\\\n\tSQUASHFS_SWAP((s)->start_block, d, 8, 24);\\\n}\n\n#    define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\\\n\tSQUASHFS_SWAP((s)->offset, d, 0, 13);\\\n\tSQUASHFS_SWAP((s)->type, d, 13, 3);\\\n\tSQUASHFS_SWAP((s)->size, d, 16, 8);\\\n}\n\n#    define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\\\n\tSQUASHFS_SWAP_START\\\n\tSQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\\\n\tSQUASHFS_SWAP((s)->start_block, d, 0, 32);\\\n\tSQUASHFS_SWAP((s)->size, d, 32, 32);\\\n}\n\n#    define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS_3(s, d, n)\n\n/* fragment and fragment table defines */\n#    define SQUASHFS_FRAGMENT_BYTES_2(A)\t((A) * sizeof(struct squashfs_fragment_entry_2))\n\n#    define SQUASHFS_FRAGMENT_INDEX_2(A)\t(SQUASHFS_FRAGMENT_BYTES_2(A) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)\t(SQUASHFS_FRAGMENT_BYTES_2(A) % \\\n\t\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_FRAGMENT_INDEXES_2(A)\t((SQUASHFS_FRAGMENT_BYTES_2(A) + \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE - 1) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)\t(SQUASHFS_FRAGMENT_INDEXES_2(A) *\\\n\t\t\t\t\t\tsizeof(int))\n/*\n * macros used to swap each structure entry, taking into account\n * bitfields and different bitfield placing conventions on differing architectures\n */\n#    if __BYTE_ORDER == __BIG_ENDIAN\n\t/* convert from big endian to little endian */\n#        define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos)\n#    else\n\t/* convert from little endian to big endian */\n#        define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos)\n#    endif\n\n#    define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\\\n\tb_pos = pos % 8;\\\n\tval = 0;\\\n\ts = (unsigned char *)p + (pos / 8);\\\n\td = ((unsigned char *) &val) + 7;\\\n\tfor(bits = 0; bits < (tbits + b_pos); bits += 8) \\\n\t\t*d-- = *s++;\\\n\tvalue = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\\\n}\n#    define SQUASHFS_MEMSET(s, d, n)\tmemset(s, 0, n);\n#endif\n"
  },
  {
    "path": "include/squashfs/squashfs_fs.h",
    "content": "#ifndef SQUASHFS_FS\n#    define SQUASHFS_FS\n/*\n * Squashfs\n *\n * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012,\n * 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * squashfs_fs.h\n */\n\n#    define SQUASHFS_CACHED_FRAGMENTS\tCONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE\n#    define SQUASHFS_MAJOR\t\t\t4\n#    define SQUASHFS_MINOR\t\t\t0\n#    define SQUASHFS_MAGIC\t\t\t0x73717368\n#    define SQUASHFS_MAGIC_SWAP\t\t0x68737173\n#    define SQUASHFS_START\t\t\t0\n\n/* size of metadata (inode and directory) blocks */\n#    define SQUASHFS_METADATA_SIZE\t\t8192\n#    define SQUASHFS_METADATA_LOG\t\t13\n\n/* default size of data blocks */\n#    define SQUASHFS_FILE_SIZE\t\t131072\n\n#    define SQUASHFS_FILE_MAX_SIZE\t\t1048576\n#    define SQUASHFS_FILE_MAX_LOG\t\t20\n\n/* Max number of uids and gids */\n#    define SQUASHFS_IDS\t\t\t65536\n\n/* Max length of filename (not 255) */\n#    define SQUASHFS_NAME_LEN\t\t256\n\n#    define SQUASHFS_INVALID\t\t((long long) 0xffffffffffff)\n#    define SQUASHFS_INVALID_FRAG\t\t((unsigned int) 0xffffffff)\n#    define SQUASHFS_INVALID_XATTR\t\t((unsigned int) 0xffffffff)\n#    define SQUASHFS_INVALID_BLK\t\t((long long) -1)\n#    define SQUASHFS_USED_BLK\t\t((long long) -2)\n\n/* Filesystem flags */\n#    define SQUASHFS_NOI\t\t\t0\n#    define SQUASHFS_NOD\t\t\t1\n#    define SQUASHFS_CHECK\t\t\t2\n#    define SQUASHFS_NOF\t\t\t3\n#    define SQUASHFS_NO_FRAG\t\t4\n#    define SQUASHFS_ALWAYS_FRAG\t\t5\n#    define SQUASHFS_DUPLICATE\t\t6\n#    define SQUASHFS_EXPORT\t\t\t7\n#    define SQUASHFS_NOX\t\t\t8\n#    define SQUASHFS_NO_XATTR\t\t9\n#    define SQUASHFS_COMP_OPT\t\t10\n\n#    define SQUASHFS_BIT(flag, bit)\t\t((flag >> bit) & 1)\n\n#    define SQUASHFS_UNCOMPRESSED_INODES(flags)\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_NOI)\n\n#    define SQUASHFS_UNCOMPRESSED_DATA(flags)\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_NOD)\n\n#    define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_NOF)\n\n#    define SQUASHFS_NO_FRAGMENTS(flags)\t\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_NO_FRAG)\n\n#    define SQUASHFS_ALWAYS_FRAGMENTS(flags)\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_ALWAYS_FRAG)\n\n#    define SQUASHFS_DUPLICATES(flags)\t\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_DUPLICATE)\n\n#    define SQUASHFS_EXPORTABLE(flags)\t\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_EXPORT)\n\n#    define SQUASHFS_UNCOMPRESSED_XATTRS(flags)\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_NOX)\n\n#    define SQUASHFS_NO_XATTRS(flags)\t\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_NO_XATTR)\n\n#    define SQUASHFS_COMP_OPTS(flags)\t\tSQUASHFS_BIT(flags, \\\n\t\t\t\t\t\tSQUASHFS_COMP_OPT)\n\n#    define SQUASHFS_MKFLAGS(noi, nod, nof, nox, no_frag, always_frag, \\\n\t\tduplicate_checking, exportable, no_xattr, comp_opt) (noi | \\\n\t\t(nod << 1) | (nof << 3) | (no_frag << 4) | \\\n\t\t(always_frag << 5) | (duplicate_checking << 6) | \\\n\t\t(exportable << 7) | (nox << 8) | (no_xattr << 9) | \\\n\t\t(comp_opt << 10))\n\n/* Max number of types and file types */\n#    define SQUASHFS_DIR_TYPE\t\t1\n#    define SQUASHFS_FILE_TYPE\t\t2\n#    define SQUASHFS_SYMLINK_TYPE\t\t3\n#    define SQUASHFS_BLKDEV_TYPE\t\t4\n#    define SQUASHFS_CHRDEV_TYPE\t\t5\n#    define SQUASHFS_FIFO_TYPE\t\t6\n#    define SQUASHFS_SOCKET_TYPE\t\t7\n#    define SQUASHFS_LDIR_TYPE\t\t8\n#    define SQUASHFS_LREG_TYPE\t\t9\n#    define SQUASHFS_LSYMLINK_TYPE\t\t10\n#    define SQUASHFS_LBLKDEV_TYPE\t\t11\n#    define SQUASHFS_LCHRDEV_TYPE\t\t12\n#    define SQUASHFS_LFIFO_TYPE\t\t13\n#    define SQUASHFS_LSOCKET_TYPE\t\t14\n\n/* Xattr types */\n#    define SQUASHFS_XATTR_USER\t\t0\n#    define SQUASHFS_XATTR_TRUSTED\t\t1\n#    define SQUASHFS_XATTR_SECURITY\t\t2\n#    define SQUASHFS_XATTR_VALUE_OOL\t256\n#    define SQUASHFS_XATTR_PREFIX_MASK\t0xff\n\n/* Flag whether block is compressed or uncompressed, bit is set if block is\n * uncompressed */\n#    define SQUASHFS_COMPRESSED_BIT\t\t(1 << 15)\n\n#    define SQUASHFS_COMPRESSED_SIZE(B)\t(((B) & ~SQUASHFS_COMPRESSED_BIT) ? \\\n\t\t(B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)\n\n#    define SQUASHFS_COMPRESSED(B)\t\t(!((B) & SQUASHFS_COMPRESSED_BIT))\n\n#    define SQUASHFS_COMPRESSED_BIT_BLOCK\t\t(1 << 24)\n\n#    define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)\t((B) & \\\n\t~SQUASHFS_COMPRESSED_BIT_BLOCK)\n\n#    define SQUASHFS_COMPRESSED_BLOCK(B)\t(!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))\n\n/*\n * Inode number ops.  Inodes consist of a compressed block number, and an\n * uncompressed  offset within that block\n */\n#    define SQUASHFS_INODE_BLK(a)\t\t((unsigned int) ((a) >> 16))\n\n#    define SQUASHFS_INODE_OFFSET(a)\t((unsigned int) ((a) & 0xffff))\n\n#    define SQUASHFS_MKINODE(A, B)\t\t((squashfs_inode)(((squashfs_inode) (A)\\\n\t\t\t\t\t<< 16) + (B)))\n\n/* Compute 32 bit VFS inode number from squashfs inode number */\n#    define SQUASHFS_MK_VFS_INODE(a, b)\t((unsigned int) (((a) << 8) + \\\n\t\t\t\t\t((b) >> 2) + 1))\n\n/* Translate between VFS mode and squashfs mode */\n#    define SQUASHFS_MODE(a)\t\t((a) & 0xfff)\n\n/* fragment and fragment table defines */\n#    define SQUASHFS_FRAGMENT_BYTES(A)\t((A) * \\\n\t\t\t\t\tsizeof(struct squashfs_fragment_entry))\n\n#    define SQUASHFS_FRAGMENT_INDEX(A)\t(SQUASHFS_FRAGMENT_BYTES(A) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)\t(SQUASHFS_FRAGMENT_BYTES(A) % \\\n\t\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_FRAGMENT_INDEXES(A)\t((SQUASHFS_FRAGMENT_BYTES(A) + \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE - 1) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_FRAGMENT_INDEX_BYTES(A)\t(SQUASHFS_FRAGMENT_INDEXES(A) *\\\n\t\t\t\t\t\tsizeof(long long))\n\n/* inode lookup table defines */\n#    define SQUASHFS_LOOKUP_BYTES(A)\t((A) * sizeof(squashfs_inode))\n\n#    define SQUASHFS_LOOKUP_BLOCK(A)\t\t(SQUASHFS_LOOKUP_BYTES(A) / \\\n\t\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_LOOKUP_BLOCK_OFFSET(A)\t\t(SQUASHFS_LOOKUP_BYTES(A) % \\\n\t\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_LOOKUP_BLOCKS(A)\t((SQUASHFS_LOOKUP_BYTES(A) + \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE - 1) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_LOOKUP_BLOCK_BYTES(A)\t(SQUASHFS_LOOKUP_BLOCKS(A) *\\\n\t\t\t\t\tsizeof(long long))\n\n/* uid lookup table defines */\n#    define SQUASHFS_ID_BYTES(A)\t((A) * sizeof(unsigned int))\n\n#    define SQUASHFS_ID_BLOCK(A)\t\t(SQUASHFS_ID_BYTES(A) / \\\n\t\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_ID_BLOCK_OFFSET(A)\t\t(SQUASHFS_ID_BYTES(A) % \\\n\t\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_ID_BLOCKS(A)\t((SQUASHFS_ID_BYTES(A) + \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE - 1) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_ID_BLOCK_BYTES(A)\t(SQUASHFS_ID_BLOCKS(A) *\\\n\t\t\t\t\tsizeof(long long))\n\n/* xattr id lookup table defines */\n#    define SQUASHFS_XATTR_BYTES(A)\t\t((A) * sizeof(struct squashfs_xattr_id))\n\n#    define SQUASHFS_XATTR_BLOCK(A)\t\t(SQUASHFS_XATTR_BYTES(A) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_XATTR_BLOCK_OFFSET(A)\t(SQUASHFS_XATTR_BYTES(A) % \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_XATTR_BLOCKS(A)\t((SQUASHFS_XATTR_BYTES(A) + \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE - 1) / \\\n\t\t\t\t\tSQUASHFS_METADATA_SIZE)\n\n#    define SQUASHFS_XATTR_BLOCK_BYTES(A)\t(SQUASHFS_XATTR_BLOCKS(A) *\\\n\t\t\t\t\tsizeof(long long))\n\n#    define SQUASHFS_XATTR_BLK(A)\t\t((unsigned int) ((A) >> 16))\n\n#    define SQUASHFS_XATTR_OFFSET(A)\t((unsigned int) ((A) & 0xffff))\n\n/* cached data constants for filesystem */\n#    define SQUASHFS_CACHED_BLKS\t\t8\n\n#    define SQUASHFS_MAX_FILE_SIZE_LOG\t64\n\n#    define SQUASHFS_MAX_FILE_SIZE\t\t((long long) 1 << \\\n\t\t\t\t\t(SQUASHFS_MAX_FILE_SIZE_LOG - 2))\n\n#    define SQUASHFS_MARKER_BYTE\t\t0xff\n\n/* meta index cache */\n#    define SQUASHFS_META_INDEXES\t(SQUASHFS_METADATA_SIZE / sizeof(unsigned int))\n#    define SQUASHFS_META_ENTRIES\t31\n#    define SQUASHFS_META_NUMBER\t8\n#    define SQUASHFS_SLOTS\t\t4\n\nstruct meta_entry {\n\tlong long data_block;\n\tunsigned int index_block;\n\tunsigned short offset;\n\tunsigned short pad;\n};\n\nstruct meta_index {\n\tunsigned int inode_number;\n\tunsigned int offset;\n\tunsigned short entries;\n\tunsigned short skip;\n\tunsigned short locked;\n\tunsigned short pad;\n\tstruct meta_entry meta_entry[SQUASHFS_META_ENTRIES];\n};\n\n/*\n * definitions for structures on disk\n */\n\ntypedef long long squashfs_block;\ntypedef long long squashfs_inode;\n\n#    define ZLIB_COMPRESSION\t1\n#    define LZMA_COMPRESSION\t2\n#    define LZO_COMPRESSION\t\t3\n#    define XZ_COMPRESSION\t\t4\n#    define LZ4_COMPRESSION\t\t5\n\nstruct squashfs_super_block {\n\tunsigned int s_magic;\n\tunsigned int inodes;\n\tint mkfs_time /* time of filesystem creation */ ;\n\tunsigned int block_size;\n\tunsigned int fragments;\n\tunsigned short compression;\n\tunsigned short block_log;\n\tunsigned short flags;\n\tunsigned short no_ids;\n\tunsigned short s_major;\n\tunsigned short s_minor;\n\tsquashfs_inode root_inode;\n\tlong long bytes_used;\n\tlong long id_table_start;\n\tlong long xattr_id_table_start;\n\tlong long inode_table_start;\n\tlong long directory_table_start;\n\tlong long fragment_table_start;\n\tlong long lookup_table_start;\n};\n\nstruct squashfs_dir_index {\n\tunsigned int index;\n\tunsigned int start_block;\n\tunsigned int size;\n\tunsigned char name[0];\n};\n\nstruct squashfs_base_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n};\n\nstruct squashfs_ipc_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n};\n\nstruct squashfs_lipc_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tunsigned int xattr;\n};\n\nstruct squashfs_dev_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tunsigned int rdev;\n};\n\nstruct squashfs_ldev_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tunsigned int rdev;\n\tunsigned int xattr;\n};\n\nstruct squashfs_symlink_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tunsigned int symlink_size;\n\tchar symlink[0];\n};\n\nstruct squashfs_reg_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int start_block;\n\tunsigned int fragment;\n\tunsigned int offset;\n\tunsigned int file_size;\n\tunsigned int block_list[0];\n};\n\nstruct squashfs_lreg_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n\tsquashfs_block start_block;\n\tlong long file_size;\n\tlong long sparse;\n\tunsigned int nlink;\n\tunsigned int fragment;\n\tunsigned int offset;\n\tunsigned int xattr;\n\tunsigned int block_list[0];\n};\n\nstruct squashfs_dir_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int start_block;\n\tunsigned int nlink;\n\tunsigned short file_size;\n\tunsigned short offset;\n\tunsigned int parent_inode;\n};\n\nstruct squashfs_ldir_inode_header {\n\tunsigned short inode_type;\n\tunsigned short mode;\n\tunsigned short uid;\n\tunsigned short guid;\n\tint mtime;\n\tunsigned int inode_number;\n\tunsigned int nlink;\n\tunsigned int file_size;\n\tunsigned int start_block;\n\tunsigned int parent_inode;\n\tunsigned short i_count;\n\tunsigned short offset;\n\tunsigned int xattr;\n\tstruct squashfs_dir_index index[0];\n};\n\nunion squashfs_inode_header {\n\tstruct squashfs_base_inode_header base;\n\tstruct squashfs_dev_inode_header dev;\n\tstruct squashfs_ldev_inode_header ldev;\n\tstruct squashfs_symlink_inode_header symlink;\n\tstruct squashfs_reg_inode_header reg;\n\tstruct squashfs_lreg_inode_header lreg;\n\tstruct squashfs_dir_inode_header dir;\n\tstruct squashfs_ldir_inode_header ldir;\n\tstruct squashfs_ipc_inode_header ipc;\n\tstruct squashfs_lipc_inode_header lipc;\n};\n\nstruct squashfs_dir_entry {\n\tunsigned short offset;\n\tshort inode_number;\n\tunsigned short type;\n\tunsigned short size;\n\tchar name[0];\n};\n\nstruct squashfs_dir_header {\n\tunsigned int count;\n\tunsigned int start_block;\n\tunsigned int inode_number;\n};\n\nstruct squashfs_fragment_entry {\n\tlong long start_block;\n\tunsigned int size;\n\tunsigned int unused;\n};\n\nstruct squashfs_xattr_entry {\n\tunsigned short type;\n\tunsigned short size;\n};\n\nstruct squashfs_xattr_val {\n\tunsigned int vsize;\n};\n\nstruct squashfs_xattr_id {\n\tlong long xattr;\n\tunsigned int count;\n\tunsigned int size;\n};\n\nstruct squashfs_xattr_table {\n\tlong long xattr_table_start;\n\tunsigned int xattr_ids;\n\tunsigned int unused;\n};\n\n#endif\n"
  },
  {
    "path": "include/squashfs/squashfs_swap.h",
    "content": "#ifndef SQUASHFS_SWAP_H\n#    define SQUASHFS_SWAP_H\n/*\n * Squashfs\n *\n * Copyright (c) 2008, 2009, 2010, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * squashfs_swap.h\n */\n\n/*\n * macros to convert each stucture from big endian to little endian\n */\n\n#    if __BYTE_ORDER == __BIG_ENDIAN\n#        include <stddef.h>\nextern void swap_le16(void *, void *);\nextern void swap_le32(void *, void *);\nextern void swap_le64(void *, void *);\nextern void swap_le16_num(void *, void *, int);\nextern void swap_le32_num(void *, void *, int);\nextern void swap_le64_num(void *, void *, int);\nextern unsigned short inswap_le16(unsigned short);\nextern unsigned int inswap_le32(unsigned int);\nextern long long inswap_le64(long long);\nextern void inswap_le16_num(unsigned short *, int);\nextern void inswap_le32_num(unsigned int *, int);\nextern void inswap_le64_num(long long *, int);\n\n#        define _SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(32, s, d, s_magic, struct squashfs_super_block);\\\n\tSWAP_FUNC(32, s, d, inodes, struct squashfs_super_block);\\\n\tSWAP_FUNC##S(32, s, d, mkfs_time, struct squashfs_super_block);\\\n\tSWAP_FUNC(32, s, d, block_size, struct squashfs_super_block);\\\n\tSWAP_FUNC(32, s, d, fragments, struct squashfs_super_block);\\\n\tSWAP_FUNC(16, s, d, compression, struct squashfs_super_block);\\\n\tSWAP_FUNC(16, s, d, block_log, struct squashfs_super_block);\\\n\tSWAP_FUNC(16, s, d, flags, struct squashfs_super_block);\\\n\tSWAP_FUNC(16, s, d, no_ids, struct squashfs_super_block);\\\n\tSWAP_FUNC(16, s, d, s_major, struct squashfs_super_block);\\\n\tSWAP_FUNC(16, s, d, s_minor, struct squashfs_super_block);\\\n\tSWAP_FUNC(64, s, d, root_inode, struct squashfs_super_block);\\\n\tSWAP_FUNC(64, s, d, bytes_used, struct squashfs_super_block);\\\n\tSWAP_FUNC(64, s, d, id_table_start, struct squashfs_super_block);\\\n\tSWAP_FUNC(64, s, d, xattr_id_table_start, struct squashfs_super_block);\\\n\tSWAP_FUNC(64, s, d, inode_table_start, struct squashfs_super_block);\\\n\tSWAP_FUNC(64, s, d, directory_table_start, struct squashfs_super_block);\\\n\tSWAP_FUNC(64, s, d, fragment_table_start, struct squashfs_super_block);\\\n\tSWAP_FUNC(64, s, d, lookup_table_start, struct squashfs_super_block);\\\n}\n\n#        define _SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(32, s, d, index, struct squashfs_dir_index);\\\n\tSWAP_FUNC(32, s, d, start_block, struct squashfs_dir_index);\\\n\tSWAP_FUNC(32, s, d, size, struct squashfs_dir_index);\\\n}\n\n#        define _SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_base_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_base_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_base_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_base_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_base_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_base_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_ipc_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_ipc_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_ipc_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_ipc_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_ipc_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_ipc_inode_header);\\\n\tSWAP_FUNC(32, s, d, nlink, struct squashfs_ipc_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_lipc_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_lipc_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_lipc_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_lipc_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_lipc_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_lipc_inode_header);\\\n\tSWAP_FUNC(32, s, d, nlink, struct squashfs_lipc_inode_header);\\\n\tSWAP_FUNC(32, s, d, xattr, struct squashfs_lipc_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_dev_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_dev_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_dev_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_dev_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_dev_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_dev_inode_header);\\\n\tSWAP_FUNC(32, s, d, nlink, struct squashfs_dev_inode_header);\\\n\tSWAP_FUNC(32, s, d, rdev, struct squashfs_dev_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_ldev_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_ldev_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_ldev_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_ldev_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_ldev_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_ldev_inode_header);\\\n\tSWAP_FUNC(32, s, d, nlink, struct squashfs_ldev_inode_header);\\\n\tSWAP_FUNC(32, s, d, rdev, struct squashfs_ldev_inode_header);\\\n\tSWAP_FUNC(32, s, d, xattr, struct squashfs_ldev_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_symlink_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_symlink_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_symlink_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_symlink_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_symlink_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_symlink_inode_header);\\\n\tSWAP_FUNC(32, s, d, nlink, struct squashfs_symlink_inode_header);\\\n\tSWAP_FUNC(32, s, d, symlink_size, struct squashfs_symlink_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_reg_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_reg_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_reg_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_reg_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_reg_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_reg_inode_header);\\\n\tSWAP_FUNC(32, s, d, start_block, struct squashfs_reg_inode_header);\\\n\tSWAP_FUNC(32, s, d, fragment, struct squashfs_reg_inode_header);\\\n\tSWAP_FUNC(32, s, d, offset, struct squashfs_reg_inode_header);\\\n\tSWAP_FUNC(32, s, d, file_size, struct squashfs_reg_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(64, s, d, start_block, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(64, s, d, file_size, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(64, s, d, sparse, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(32, s, d, nlink, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(32, s, d, fragment, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(32, s, d, offset, struct squashfs_lreg_inode_header);\\\n\tSWAP_FUNC(32, s, d, xattr, struct squashfs_lreg_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC(32, s, d, start_block, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC(32, s, d, nlink, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC(16, s, d, file_size, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC(16, s, d, offset, struct squashfs_dir_inode_header);\\\n\tSWAP_FUNC(32, s, d, parent_inode, struct squashfs_dir_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, inode_type, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(16, s, d, mode, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(16, s, d, uid, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(16, s, d, guid, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC##S(32, s, d, mtime, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(32, s, d, nlink, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(32, s, d, file_size, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(32, s, d, start_block, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(32, s, d, parent_inode, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(16, s, d, i_count, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(16, s, d, offset, struct squashfs_ldir_inode_header);\\\n\tSWAP_FUNC(32, s, d, xattr, struct squashfs_ldir_inode_header);\\\n}\n\n#        define _SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, offset, struct squashfs_dir_entry);\\\n\tSWAP_FUNC##S(16, s, d, inode_number, struct squashfs_dir_entry);\\\n\tSWAP_FUNC(16, s, d, type, struct squashfs_dir_entry);\\\n\tSWAP_FUNC(16, s, d, size, struct squashfs_dir_entry);\\\n}\n\n#        define _SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(32, s, d, count, struct squashfs_dir_header);\\\n\tSWAP_FUNC(32, s, d, start_block, struct squashfs_dir_header);\\\n\tSWAP_FUNC(32, s, d, inode_number, struct squashfs_dir_header);\\\n}\n\n#        define _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(64, s, d, start_block, struct squashfs_fragment_entry);\\\n\tSWAP_FUNC(32, s, d, size, struct squashfs_fragment_entry);\\\n}\n\n#        define _SQUASHFS_SWAP_XATTR_ENTRY(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(16, s, d, type, struct squashfs_xattr_entry);\\\n\tSWAP_FUNC(16, s, d, size, struct squashfs_xattr_entry);\\\n}\n\n#        define _SQUASHFS_SWAP_XATTR_VAL(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(32, s, d, vsize, struct squashfs_xattr_val);\\\n}\n\n#        define _SQUASHFS_SWAP_XATTR_ID(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(64, s, d, xattr, struct squashfs_xattr_id);\\\n\tSWAP_FUNC(32, s, d, count, struct squashfs_xattr_id);\\\n\tSWAP_FUNC(32, s, d, size, struct squashfs_xattr_id);\\\n}\n\n#        define _SQUASHFS_SWAP_XATTR_TABLE(s, d, SWAP_FUNC) {\\\n\tSWAP_FUNC(64, s, d, xattr_table_start, struct squashfs_xattr_table);\\\n\tSWAP_FUNC(32, s, d, xattr_ids, struct squashfs_xattr_table);\\\n}\n\n/* big endian architecture copy and swap macros */\n#        define SQUASHFS_SWAP_SUPER_BLOCK(s, d)\t\\\n\t\t\t_SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_DIR_INDEX(s, d) \\\n\t\t\t_SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_DIR_ENTRY(s, d) \\\n\t\t\t_SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_DIR_HEADER(s, d) \\\n\t\t\t_SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \\\n\t\t\t_SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_XATTR_ENTRY(s, d) \\\n\t\t\t _SQUASHFS_SWAP_XATTR_ENTRY(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_XATTR_VAL(s, d) \\\n\t\t\t_SQUASHFS_SWAP_XATTR_VAL(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_XATTR_ID(s, d) \\\n\t\t\t _SQUASHFS_SWAP_XATTR_ID(s, d, SWAP_LE)\n#        define SQUASHFS_SWAP_XATTR_TABLE(s, d) \\\n\t\t\t_SQUASHFS_SWAP_XATTR_TABLE(s, d, SWAP_LE)\n#        define SWAP_LE(bits, s, d, field, type) \\\n\t\t\tSWAP_LE##bits(((void *)(s)) + offsetof(type, field), \\\n\t\t\t\t((void *)(d)) + offsetof(type, field))\n#        define SWAP_LES(bits, s, d, field, type) \\\n\t\t\tSWAP_LE(bits, s, d, field, type)\n#        define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)\n#        define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) \\\n\t\t\tSQUASHFS_SWAP_LONG_LONGS(s, d, n)\n#        define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\n#        define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\n\n#        define SQUASHFS_SWAP_SHORTS(s, d, n) swap_le16_num(s, d, n)\n#        define SQUASHFS_SWAP_INTS(s, d, n) swap_le32_num(s, d, n)\n#        define SQUASHFS_SWAP_LONG_LONGS(s, d, n) swap_le64_num(s, d, n)\n\n#        define SWAP_LE16(s, d)\t\tswap_le16(s, d)\n#        define SWAP_LE32(s, d)\t\tswap_le32(s, d)\n#        define SWAP_LE64(s, d)\t\tswap_le64(s, d)\n\n/* big endian architecture swap in-place macros */\n#        define SQUASHFS_INSWAP_SUPER_BLOCK(s) \\\n\t\t\t_SQUASHFS_SWAP_SUPER_BLOCK(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_DIR_INDEX(s) \\\n\t\t\t_SQUASHFS_SWAP_DIR_INDEX(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_BASE_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_BASE_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_IPC_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_IPC_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_LIPC_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_LIPC_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_DEV_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_DEV_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_LDEV_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_LDEV_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_REG_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_REG_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_LREG_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_LREG_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_DIR_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_DIR_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_LDIR_INODE_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_DIR_ENTRY(s) \\\n\t\t\t_SQUASHFS_SWAP_DIR_ENTRY(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_DIR_HEADER(s) \\\n\t\t\t_SQUASHFS_SWAP_DIR_HEADER(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s) \\\n\t\t\t_SQUASHFS_SWAP_FRAGMENT_ENTRY(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_XATTR_ENTRY(s) \\\n\t\t\t _SQUASHFS_SWAP_XATTR_ENTRY(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_XATTR_VAL(s) \\\n\t\t\t_SQUASHFS_SWAP_XATTR_VAL(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_XATTR_ID(s) \\\n\t\t\t _SQUASHFS_SWAP_XATTR_ID(s, s, INSWAP_LE)\n#        define SQUASHFS_INSWAP_XATTR_TABLE(s) \\\n\t\t\t_SQUASHFS_SWAP_XATTR_TABLE(s, s, INSWAP_LE)\n#        define INSWAP_LE(bits, s, d, field, type) \\\n\t\t\t(s)->field = inswap_le##bits((s)->field)\n#        define INSWAP_LES(bits, s, d, field, type) \\\n\t\t\t(s)->field = INSWAP_LES##bits((s)->field)\n#        define INSWAP_LES16(num) (short) inswap_le16((unsigned short) (num))\n#        define INSWAP_LES32(num) (int) inswap_le32((unsigned int) (num))\n#        define SQUASHFS_INSWAP_INODE_T(s) s = inswap_le64(s)\n#        define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n) inswap_le64_num(s, n)\n#        define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n) inswap_le64_num(s, n)\n#        define SQUASHFS_INSWAP_ID_BLOCKS(s, n) inswap_le64_num(s, n)\n#        define SQUASHFS_INSWAP_SHORTS(s, n) inswap_le16_num(s, n)\n#        define SQUASHFS_INSWAP_INTS(s, n) inswap_le32_num(s, n)\n#        define SQUASHFS_INSWAP_LONG_LONGS(s, n) inswap_le64_num(s, n)\n#    else\n/* little endian architecture, just copy */\n#        define SQUASHFS_SWAP_SUPER_BLOCK(s, d)\t\\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_super_block))\n#        define SQUASHFS_SWAP_DIR_INDEX(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_dir_index))\n#        define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_base_inode_header))\n#        define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_ipc_inode_header))\n#        define SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_lipc_inode_header))\n#        define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_dev_inode_header))\n#        define SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_ldev_inode_header))\n#        define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_symlink_inode_header))\n#        define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_reg_inode_header))\n#        define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_lreg_inode_header))\n#        define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_dir_inode_header))\n#        define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_ldir_inode_header))\n#        define SQUASHFS_SWAP_DIR_ENTRY(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_dir_entry))\n#        define SQUASHFS_SWAP_DIR_HEADER(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_dir_header))\n#        define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_fragment_entry))\n#        define SQUASHFS_SWAP_XATTR_ENTRY(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_xattr_entry))\n#        define SQUASHFS_SWAP_XATTR_VAL(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_xattr_val))\n#        define SQUASHFS_SWAP_XATTR_ID(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_xattr_id))\n#        define SQUASHFS_SWAP_XATTR_TABLE(s, d) \\\n\t\tSQUASHFS_MEMCPY(s, d, sizeof(struct squashfs_xattr_table))\n#        define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)\n#        define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) \\\n\t\t\tSQUASHFS_SWAP_LONG_LONGS(s, d, n)\n#        define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\n#        define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\n\n#        define SQUASHFS_MEMCPY(s, d, n)\tmemcpy(d, s, n)\n#        define SQUASHFS_SWAP_SHORTS(s, d, n)\tmemcpy(d, s, n * sizeof(short))\n#        define SQUASHFS_SWAP_INTS(s, d, n)\tmemcpy(d, s, n * sizeof(int))\n#        define SQUASHFS_SWAP_LONG_LONGS(s, d, n) \\\n\t\t\t\t\tmemcpy(d, s, n * sizeof(long long))\n\n/* little endian architecture, data already in place so do nothing */\n#        define SQUASHFS_INSWAP_SUPER_BLOCK(s)\n#        define SQUASHFS_INSWAP_DIR_INDEX(s)\n#        define SQUASHFS_INSWAP_BASE_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_IPC_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_LIPC_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_DEV_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_LDEV_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_REG_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_LREG_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_DIR_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s)\n#        define SQUASHFS_INSWAP_DIR_ENTRY(s)\n#        define SQUASHFS_INSWAP_DIR_HEADER(s)\n#        define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s)\n#        define SQUASHFS_INSWAP_XATTR_ENTRY(s)\n#        define SQUASHFS_INSWAP_XATTR_VAL(s)\n#        define SQUASHFS_INSWAP_XATTR_ID(s)\n#        define SQUASHFS_INSWAP_XATTR_TABLE(s)\n#        define SQUASHFS_INSWAP_INODE_T(s)\n#        define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n)\n#        define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n)\n#        define SQUASHFS_INSWAP_ID_BLOCKS(s, n)\n#        define SQUASHFS_INSWAP_SHORTS(s, n)\n#        define SQUASHFS_INSWAP_INTS(s, n)\n#        define SQUASHFS_INSWAP_LONG_LONGS(s, n)\n#    endif\n#endif\n"
  },
  {
    "path": "include/squashfs/unsquashfs.h",
    "content": "#ifndef UNSQUASHFS_H\n#    define UNSQUASHFS_H\n/*\n * Unsquash a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2009, 2010, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * unsquashfs.h\n */\n\n#    define TRUE 1\n#    define FALSE 0\n#    include <stdio.h>\n#    include <sys/types.h>\n#    include <unistd.h>\n#    include <stdlib.h>\n#    include <sys/stat.h>\n#    include <fcntl.h>\n#    include <errno.h>\n#    include <string.h>\n#    include <sys/mman.h>\n#    include <utime.h>\n#    include <pwd.h>\n#    include <grp.h>\n#    include <time.h>\n#    include <regex.h>\n#    include <fnmatch.h>\n#    include <signal.h>\n#    include <pthread.h>\n#    include <math.h>\n#    include <sys/ioctl.h>\n#    include <sys/time.h>\n\n#    ifndef __APPLE__\n#        include <sys/sysmacros.h>\n#    endif\n\n#    if defined(__CYGWIN__) || defined(__APPLE__)\n#        define FNM_EXTMATCH  (1 << 5)\n#    endif\n\n#    if !defined(linux) && !defined(__CYGWIN__)\n#        define __BYTE_ORDER BYTE_ORDER\n#        define __BIG_ENDIAN BIG_ENDIAN\n#        define __LITTLE_ENDIAN LITTLE_ENDIAN\n#    else\n#        include <endian.h>\n#    endif\n\n#    include \"squashfs_fs.h\"\n#    include \"error.h\"\n\n#    define CALCULATE_HASH(start)\t(start & 0xffff)\n\n/*\n * Unified superblock containing fields for all superblocks\n */\nstruct super_block {\n\tstruct squashfs_super_block s;\n\t/* fields only used by squashfs 3 and earlier layouts */\n\tunsigned int no_uids;\n\tunsigned int no_guids;\n\tlong long uid_start;\n\tlong long guid_start;\n};\n\nstruct hash_table_entry {\n\tlong long start;\n\tint bytes;\n\tstruct hash_table_entry *next;\n};\n\nstruct inode {\n\tint blocks;\n\tchar *block_ptr;\n\tlong long data;\n\tint fragment;\n\tint frag_bytes;\n\tgid_t gid;\n\tint inode_number;\n\tint mode;\n\tint offset;\n\tlong long start;\n\tchar *symlink;\n\ttime_t time;\n\tint type;\n\tuid_t uid;\n\tchar sparse;\n\tunsigned int xattr;\n};\n\ntypedef struct squashfs_operations {\n\tstruct dir *(*squashfs_opendir) (unsigned int block_start, unsigned int offset, struct inode ** i);\n\tvoid (*read_fragment) (unsigned int fragment, long long *start_block, int *size);\n\tint (*read_fragment_table) (long long *);\n\tvoid (*read_block_list) (unsigned int *block_list, char *block_ptr, int blocks);\n\tstruct inode *(*read_inode) (unsigned int start_block, unsigned int offset);\n\tint (*read_uids_guids) ();\n} squashfs_operations;\n\nstruct test {\n\tint mask;\n\tint value;\n\tint position;\n\tchar mode;\n};\n\n/* Cache status struct.  Caches are used to keep\n  track of memory buffers passed between different threads */\nstruct cache {\n\tint max_buffers;\n\tint count;\n\tint used;\n\tint buffer_size;\n\tint wait_free;\n\tint wait_pending;\n\tpthread_mutex_t mutex;\n\tpthread_cond_t wait_for_free;\n\tpthread_cond_t wait_for_pending;\n\tstruct cache_entry *free_list;\n\tstruct cache_entry *hash_table[65536];\n};\n\n/* struct describing a cache entry passed between threads */\nstruct cache_entry {\n\tstruct cache *cache;\n\tlong long block;\n\tint size;\n\tint used;\n\tint error;\n\tint pending;\n\tstruct cache_entry *hash_next;\n\tstruct cache_entry *hash_prev;\n\tstruct cache_entry *free_next;\n\tstruct cache_entry *free_prev;\n\tchar *data;\n};\n\n/* struct describing queues used to pass data between threads */\nstruct queue {\n\tint size;\n\tint readp;\n\tint writep;\n\tpthread_mutex_t mutex;\n\tpthread_cond_t empty;\n\tpthread_cond_t full;\n\tvoid **data;\n};\n\n/* default size of fragment buffer in Mbytes */\n#    define FRAGMENT_BUFFER_DEFAULT 256\n/* default size of data buffer in Mbytes */\n#    define DATA_BUFFER_DEFAULT 256\n\n#    define DIR_ENT_SIZE\t16\n\nstruct dir_ent {\n\tchar name[SQUASHFS_NAME_LEN + 1];\n\tunsigned int start_block;\n\tunsigned int offset;\n\tunsigned int type;\n};\n\nstruct dir {\n\tint dir_count;\n\tint cur_entry;\n\tunsigned int mode;\n\tuid_t uid;\n\tgid_t guid;\n\tunsigned int mtime;\n\tunsigned int xattr;\n\tstruct dir_ent *dirs;\n};\n\nstruct file_entry {\n\tint offset;\n\tint size;\n\tstruct cache_entry *buffer;\n};\n\nstruct squashfs_file {\n\tint fd;\n\tint blocks;\n\tlong long file_size;\n\tint mode;\n\tuid_t uid;\n\tgid_t gid;\n\ttime_t time;\n\tchar *pathname;\n\tchar sparse;\n\tunsigned int xattr;\n};\n\nstruct path_entry {\n\tchar *name;\n\tregex_t *preg;\n\tstruct pathname *paths;\n};\n\nstruct pathname {\n\tint names;\n\tstruct path_entry *name;\n};\n\nstruct pathnames {\n\tint count;\n\tstruct pathname *path[0];\n};\n#    define PATHS_ALLOC_SIZE 10\n\n/* globals */\nextern struct super_block sBlk;\nextern squashfs_operations s_ops;\nextern int swap;\nextern char *inode_table, *directory_table;\nextern struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536];\nextern unsigned int *uid_table, *guid_table;\nextern pthread_mutex_t screen_mutex;\nextern int progress_enabled;\nextern int inode_number;\nextern int lookup_type[];\nextern int fd;\nextern struct queue *to_reader, *to_inflate, *to_writer;\nextern struct cache *fragment_cache, *data_cache;\n\n/* unsquashfs.c */\nextern int lookup_entry(struct hash_table_entry **, long long);\nextern int read_fs_bytes(int fd, long long, int, void *);\nextern int read_block(int, long long, long long *, int, void *);\nextern void enable_progress_bar();\nextern void disable_progress_bar();\nextern void dump_queue(struct queue *);\nextern void dump_cache(struct cache *);\nextern int is_squashfs(char *filename);\nextern int unsquashfs(char *squashfs, char *dest);\n\n/* unsquash-1.c */\nextern void read_block_list_1(unsigned int *, char *, int);\nextern int read_fragment_table_1(long long *);\nextern struct inode *read_inode_1(unsigned int, unsigned int);\nextern struct dir *squashfs_opendir_1(unsigned int, unsigned int, struct inode **);\nextern int read_uids_guids_1();\n\n/* unsquash-2.c */\nextern void read_block_list_2(unsigned int *, char *, int);\nextern int read_fragment_table_2(long long *);\nextern void read_fragment_2(unsigned int, long long *, int *);\nextern struct inode *read_inode_2(unsigned int, unsigned int);\n\n/* unsquash-3.c */\nextern int read_fragment_table_3(long long *);\nextern void read_fragment_3(unsigned int, long long *, int *);\nextern struct inode *read_inode_3(unsigned int, unsigned int);\nextern struct dir *squashfs_opendir_3(unsigned int, unsigned int, struct inode **);\n\n/* unsquash-4.c */\nextern int read_fragment_table_4(long long *);\nextern void read_fragment_4(unsigned int, long long *, int *);\nextern struct inode *read_inode_4(unsigned int, unsigned int);\nextern struct dir *squashfs_opendir_4(unsigned int, unsigned int, struct inode **);\nextern int read_uids_guids_4();\n#endif\n"
  },
  {
    "path": "include/squashfs/unsquashfs_info.h",
    "content": "#ifndef UNSQUASHFS_INFO_H\n#    define UNSQUASHFS_INFO_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * unsquashfs_info.h\n */\n\nextern void disable_info();\nextern void update_info(char *);\nextern void init_info();\n#endif\n"
  },
  {
    "path": "include/squashfs/xattr.h",
    "content": "#ifndef XATTR_H\n#    define XATTR_H\n/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2010, 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * xattr.h\n */\n\n#    define XATTR_VALUE_OOL\t\tSQUASHFS_XATTR_VALUE_OOL\n#    define XATTR_PREFIX_MASK\tSQUASHFS_XATTR_PREFIX_MASK\n\n#    define XATTR_VALUE_OOL_SIZE\tsizeof(long long)\n\n/* maximum size of xattr value data that will be inlined */\n#    define XATTR_INLINE_MAX \t128\n\n/* the target size of an inode's xattr name:value list.  If it\n * exceeds this, then xattr value data will be successively out of lined\n * until it meets the target */\n#    define XATTR_TARGET_MAX\t65536\n\n#    define IS_XATTR(a)\t\t(a != SQUASHFS_INVALID_XATTR)\n\nstruct xattr_list {\n\tchar *name;\n\tchar *full_name;\n\tint size;\n\tint vsize;\n\tvoid *value;\n\tint type;\n\tlong long ool_value;\n\tunsigned short vchecksum;\n\tstruct xattr_list *vnext;\n};\n\nstruct dupl_id {\n\tstruct xattr_list *xattr_list;\n\tint xattrs;\n\tint xattr_id;\n\tstruct dupl_id *next;\n};\n\nstruct prefix {\n\tchar *prefix;\n\tint type;\n};\n\nextern int generate_xattrs(int, struct xattr_list *);\n\n#    ifdef XATTR_SUPPORT\nextern int get_xattrs(int, struct squashfs_super_block *);\nextern int read_xattrs(void *);\nextern long long write_xattrs();\nextern void save_xattrs();\nextern void restore_xattrs();\nextern unsigned int xattr_bytes, total_xattr_bytes;\nextern void write_xattr(char *, unsigned int);\nextern int read_xattrs_from_disk(int, struct squashfs_super_block *);\nextern struct xattr_list *get_xattr(int, unsigned int *, int);\nextern void free_xattr(struct xattr_list *, int);\n#    else\nstatic inline int get_xattrs(int fd, struct squashfs_super_block *sBlk) {\n\tif (sBlk->xattr_id_table_start != SQUASHFS_INVALID_BLK) {\n\t\tfprintf(stderr, \"Xattrs in filesystem! These are not \" \"supported on this version of Squashfs\\n\");\n\t\treturn 0;\n\t} else\n\t\treturn SQUASHFS_INVALID_BLK;\n}\n\nstatic inline int read_xattrs(void *dir_ent) {\n\treturn SQUASHFS_INVALID_XATTR;\n}\n\nstatic inline long long write_xattrs() {\n\treturn SQUASHFS_INVALID_BLK;\n}\n\nstatic inline void save_xattrs() {\n}\n\nstatic inline void restore_xattrs() {\n}\n\nstatic inline void write_xattr(char *pathname, unsigned int xattr) {\n}\n\nstatic inline int read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk) {\n\tif (sBlk->xattr_id_table_start != SQUASHFS_INVALID_BLK) {\n\t\tfprintf(stderr, \"Xattrs in filesystem! These are not \" \"supported on this version of Squashfs\\n\");\n\t\treturn 0;\n\t} else\n\t\treturn SQUASHFS_INVALID_BLK;\n}\n\nstatic inline struct xattr_list *get_xattr(int i, unsigned int *count, int j) {\n\treturn NULL;\n}\n#    endif\n\n#    ifdef XATTR_SUPPORT\n#        ifdef XATTR_DEFAULT\n#            define NOXOPT_STR\n#            define XOPT_STR \" (default)\"\n#            define XATTR_DEF 0\n#        else\n#            define NOXOPT_STR \" (default)\"\n#            define XOPT_STR\n#            define XATTR_DEF 1\n#        endif\n#    else\n#        define NOXOPT_STR \" (default)\"\n#        define XOPT_STR \" (unsupported)\"\n#        define XATTR_DEF 1\n#    endif\n#endif\n\n#ifdef __APPLE__\n#define llistxattr(path, list, size) \\\n(listxattr(path, list, size, XATTR_NOFOLLOW))\n#define lgetxattr(path, name, value, size) \\\n(getxattr(path, name, value, size, 0, XATTR_NOFOLLOW))\n#define lsetxattr(path, name, value, size, flags) \\\n(setxattr(path, name, value, size, 0, flags | XATTR_NOFOLLOW))\n#endif\n"
  },
  {
    "path": "include/squashfs/xz_wrapper.h",
    "content": "#ifndef XZ_WRAPPER_H\n#    define XZ_WRAPPER_H\n/*\n * Squashfs\n *\n * Copyright (c) 2010\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * xz_wrapper.h\n *\n */\n\n#    if !defined(linux) && !defined(__CYGWIN__)\n#        define __BYTE_ORDER BYTE_ORDER\n#        define __BIG_ENDIAN BIG_ENDIAN\n#        define __LITTLE_ENDIAN LITTLE_ENDIAN\n#    else\n#        include <endian.h>\n#    endif\n\n#    if __BYTE_ORDER == __BIG_ENDIAN\nextern unsigned int inswap_le32(unsigned int);\n\n#        define SQUASHFS_INSWAP_COMP_OPTS(s) { \\\n\t(s)->dictionary_size = inswap_le32((s)->dictionary_size); \\\n\t(s)->flags = inswap_le32((s)->flags); \\\n}\n#    else\n#        define SQUASHFS_INSWAP_COMP_OPTS(s)\n#    endif\n\n#    define MEMLIMIT (32 * 1024 * 1024)\n\nstruct bcj {\n\tchar *name;\n\tlzma_vli id;\n\tint selected;\n};\n\nstruct filter {\n\tvoid *buffer;\n\tlzma_filter filter[3];\n\tsize_t length;\n};\n\nstruct xz_stream {\n\tstruct filter *filter;\n\tint filters;\n\tint dictionary_size;\n\tlzma_options_lzma opt;\n};\n\nstruct comp_opts {\n\tint dictionary_size;\n\tint flags;\n};\n#endif\n"
  },
  {
    "path": "include/stream/crc32.h",
    "content": "#ifndef CRC32_H\n#define CRC32_H\n\n#include <stdint.h>\nuint32_t str_crc32(const unsigned char *data, int len);\n\n#endif /* CRC32_H */\n\n"
  },
  {
    "path": "include/stream/tsfile.h",
    "content": "/**\n * Copyright 2016 lprot\n * All right reserved\n */\n#ifndef __TSFILE_H\n#define __TSFILE_H\n#include <stdint.h>\n\nstruct tsfile_options {\n\tint video_stream_type;\n\tint audio_stream_type;\n\tuint8_t append;\n};\n\nvoid convertSTR2TS(char *inFilename, struct tsfile_options *opts);\nvoid processPIF(const char *filename, char *dest_file);\nuint32_t str_crc32(const unsigned char *data, int len);\n#endif //__TSFILE_H\n"
  },
  {
    "path": "include/symfile.h",
    "content": "#ifndef _SYMFILE_H_\n#    define _SYMFILE_H_\n/*\n * Copyright (c) 2011 Roman Tokarev <roman.s.tokarev@gmail.com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the author nor the names of any co-contributors\n * may be used to endorse or promote products derived from this software\n * without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\n * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\n * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#    include <stdint.h>\n#    include <unistd.h>\n\nstruct sym_entry {\n\tuint32_t addr;\n\tuint32_t end;\n\tuint32_t sym_name_off;\n};\n\nstruct sym_table {\n\tuint32_t n_symbols;\n\tstruct sym_entry *sym_entry;\n\tuint32_t *hash;\n\tuint32_t n_dwarf_lst;\n\tstruct {\n\t\tuint32_t d1;\n\t\tuint32_t d2;\n\t} *dwarf_lst;\n\tunsigned char *dwarf_data;\n\tchar *sym_name;\n};\n\nextern struct sym_table sym_table;\n\nint symfile_load(const char *sym_fname);\nuint32_t symfile_addr_by_name(const char *name);\nconst char *symfile_name_by_addr(uint32_t addr);\nuint32_t symfile_n_symbols();\nvoid symfile_write_idc(const char *fname);\n\n#endif\n"
  },
  {
    "path": "include/thpool.h",
    "content": "/**********************************\n * @author      Johan Hanssen Seferidis\n * License:     MIT\n *\n **********************************/\n\n#ifndef _THPOOL_\n#define _THPOOL_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* =================================== API ======================================= */\n\n\ntypedef struct thpool_* threadpool;\n\n\n/**\n * @brief  Initialize threadpool\n *\n * Initializes a threadpool. This function will not return untill all\n * threads have initialized successfully.\n *\n * @example\n *\n *    ..\n *    threadpool thpool;                     //First we declare a threadpool\n *    thpool = thpool_init(4);               //then we initialize it to 4 threads\n *    ..\n *\n * @param  num_threads   number of threads to be created in the threadpool\n * @return threadpool    created threadpool on success,\n *                       NULL on error\n */\nthreadpool thpool_init(int num_threads);\n\n\n/**\n * @brief Add work to the job queue\n *\n * Takes an action and its argument and adds it to the threadpool's job queue.\n * If you want to add to work a function with more than one arguments then\n * a way to implement this is by passing a pointer to a structure.\n *\n * NOTICE: You have to cast both the function and argument to not get warnings.\n *\n * @example\n *\n *    void print_num(int num){\n *       printf(\"%d\\n\", num);\n *    }\n *\n *    int main() {\n *       ..\n *       int a = 10;\n *       thpool_add_work(thpool, (void*)print_num, (void*)a);\n *       ..\n *    }\n *\n * @param  threadpool    threadpool to which the work will be added\n * @param  function_p    pointer to function to add as work\n * @param  arg_p         pointer to an argument\n * @return 0 on successs, -1 otherwise.\n */\nint thpool_add_work(threadpool, void (*function_p)(void*), void* arg_p);\n\n\n/**\n * @brief Wait for all queued jobs to finish\n *\n * Will wait for all jobs - both queued and currently running to finish.\n * Once the queue is empty and all work has completed, the calling thread\n * (probably the main program) will continue.\n *\n * Smart polling is used in wait. The polling is initially 0 - meaning that\n * there is virtually no polling at all. If after 1 seconds the threads\n * haven't finished, the polling interval starts growing exponentially\n * untill it reaches max_secs seconds. Then it jumps down to a maximum polling\n * interval assuming that heavy processing is being used in the threadpool.\n *\n * @example\n *\n *    ..\n *    threadpool thpool = thpool_init(4);\n *    ..\n *    // Add a bunch of work\n *    ..\n *    thpool_wait(thpool);\n *    puts(\"All added work has finished\");\n *    ..\n *\n * @param threadpool     the threadpool to wait for\n * @return nothing\n */\nvoid thpool_wait(threadpool);\n\n\n/**\n * @brief Pauses all threads immediately\n *\n * The threads will be paused no matter if they are idle or working.\n * The threads return to their previous states once thpool_resume\n * is called.\n *\n * While the thread is being paused, new work can be added.\n *\n * @example\n *\n *    threadpool thpool = thpool_init(4);\n *    thpool_pause(thpool);\n *    ..\n *    // Add a bunch of work\n *    ..\n *    thpool_resume(thpool); // Let the threads start their magic\n *\n * @param threadpool    the threadpool where the threads should be paused\n * @return nothing\n */\nvoid thpool_pause(threadpool);\n\n\n/**\n * @brief Unpauses all threads if they are paused\n *\n * @example\n *    ..\n *    thpool_pause(thpool);\n *    sleep(10);              // Delay execution 10 seconds\n *    thpool_resume(thpool);\n *    ..\n *\n * @param threadpool     the threadpool where the threads should be unpaused\n * @return nothing\n */\nvoid thpool_resume(threadpool);\n\n\n/**\n * @brief Destroy the threadpool\n *\n * This will wait for the currently active threads to finish and then 'kill'\n * the whole threadpool to free up memory.\n *\n * @example\n * int main() {\n *    threadpool thpool1 = thpool_init(2);\n *    threadpool thpool2 = thpool_init(2);\n *    ..\n *    thpool_destroy(thpool1);\n *    ..\n *    return 0;\n * }\n *\n * @param threadpool     the threadpool to destroy\n * @return nothing\n */\nvoid thpool_destroy(threadpool);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/u-boot/image.h",
    "content": "/*\n * (C) Copyright 2000-2005\n * Wolfgang Denk, DENX Software Engineering, wd@denx.de.\n *\n * See file CREDITS for list of people who contributed to this\n * project.\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 as\n * published by the Free Software Foundation; either version 2 of\n * 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.\t See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston,\n * MA 02111-1307 USA\n *\n ********************************************************************\n * NOTE: This header file defines an interface to U-Boot. Including\n * this (unmodified) header file in another file is considered normal\n * use of U-Boot, and does *not* fall under the heading of \"derived\n * work\".\n ********************************************************************\n */\n\n#ifndef __IMAGE_H__\n#    define __IMAGE_H__\n\n/*\n * Operating System Codes\n */\n#    define IH_OS_INVALID\t\t0\n\t\t\t\t\t\t\t\t/* Invalid OS   */\n#    define IH_OS_OPENBSD\t\t1\n\t\t\t\t\t\t\t\t/* OpenBSD  */\n#    define IH_OS_NETBSD\t\t2\n\t\t\t\t\t\t\t\t/* NetBSD   */\n#    define IH_OS_FREEBSD\t\t3\n\t\t\t\t\t\t\t\t/* FreeBSD  */\n#    define IH_OS_4_4BSD\t\t4\n\t\t\t\t\t\t\t\t/* 4.4BSD   */\n#    define IH_OS_LINUX\t\t5\t/* Linux    */\n#    define IH_OS_SVR4\t\t6\t/* SVR4     */\n#    define IH_OS_ESIX\t\t7\t/* Esix     */\n#    define IH_OS_SOLARIS\t\t8\n\t\t\t\t\t\t\t\t/* Solaris  */\n#    define IH_OS_IRIX\t\t9\t/* Irix     */\n#    define IH_OS_SCO\t\t10\t/* SCO      */\n#    define IH_OS_DELL\t\t11\t/* Dell     */\n#    define IH_OS_NCR\t\t12\t/* NCR      */\n#    define IH_OS_LYNXOS\t\t13\n\t\t\t\t\t\t\t\t/* LynxOS   */\n#    define IH_OS_VXWORKS\t\t14\n\t\t\t\t\t\t\t\t/* VxWorks  */\n#    define IH_OS_PSOS\t\t15\t/* pSOS     */\n#    define IH_OS_QNX\t\t16\t/* QNX      */\n#    define IH_OS_U_BOOT\t\t17\n\t\t\t\t\t\t\t\t/* Firmware */\n#    define IH_OS_RTEMS\t\t18\t/* RTEMS    */\n#    define IH_OS_ARTOS\t\t19\t/* ARTOS    */\n#    define IH_OS_UNITY\t\t20\t/* Unity OS */\n\n/*\n * CPU Architecture Codes (supported by Linux)\n */\n#    define IH_CPU_INVALID\t\t0\n\t\t\t\t\t\t\t\t/* Invalid CPU  */\n#    define IH_CPU_ALPHA\t\t1\n\t\t\t\t\t\t\t\t/* Alpha    */\n#    define IH_CPU_ARM\t\t2\t/* ARM      */\n#    define IH_CPU_I386\t\t3\t/* Intel x86    */\n#    define IH_CPU_IA64\t\t4\t/* IA64     */\n#    define IH_CPU_MIPS\t\t5\t/* MIPS     */\n#    define IH_CPU_MIPS64\t\t6\n\t\t\t\t\t\t\t\t/* MIPS  64 Bit */\n#    define IH_CPU_PPC\t\t7\t/* PowerPC  */\n#    define IH_CPU_S390\t\t8\t/* IBM S390 */\n#    define IH_CPU_SH\t\t9\t/* SuperH   */\n#    define IH_CPU_SPARC\t\t10\n\t\t\t\t\t\t\t\t/* Sparc    */\n#    define IH_CPU_SPARC64\t\t11\n\t\t\t\t\t\t\t\t/* Sparc 64 Bit */\n#    define IH_CPU_M68K\t\t12\t/* M68K     */\n#    define IH_CPU_NIOS\t\t13\t/* Nios-32  */\n#    define IH_CPU_MICROBLAZE\t14\n\t\t\t\t\t\t\t\t/* MicroBlaze   */\n#    define IH_CPU_NIOS2\t\t15\n\t\t\t\t\t\t\t\t/* Nios-II  */\n#    define IH_CPU_BLACKFIN\t\t16\n\t\t\t\t\t\t\t\t/* Blackfin */\n#    define IH_CPU_AVR32\t\t17\n\t\t\t\t\t\t\t\t/* AVR32    */\n\n/*\n * Image Types\n *\n * \"Standalone Programs\" are directly runnable in the environment\n *\tprovided by U-Boot; it is expected that (if they behave\n *\twell) you can continue to work in U-Boot after return from\n *\tthe Standalone Program.\n * \"OS Kernel Images\" are usually images of some Embedded OS which\n *\twill take over control completely. Usually these programs\n *\twill install their own set of exception handlers, device\n *\tdrivers, set up the MMU, etc. - this means, that you cannot\n *\texpect to re-enter U-Boot except by resetting the CPU.\n * \"RAMDisk Images\" are more or less just data blocks, and their\n *\tparameters (address, size) are passed to an OS kernel that is\n *\tbeing started.\n * \"Multi-File Images\" contain several images, typically an OS\n *\t(Linux) kernel image and one or more data images like\n *\tRAMDisks. This construct is useful for instance when you want\n *\tto boot over the network using BOOTP etc., where the boot\n *\tserver provides just a single image file, but you want to get\n *\tfor instance an OS kernel and a RAMDisk image.\n *\n *\t\"Multi-File Images\" start with a list of image sizes, each\n *\timage size (in bytes) specified by an \"uint32_t\" in network\n *\tbyte order. This list is terminated by an \"(uint32_t)0\".\n *\tImmediately after the terminating 0 follow the images, one by\n *\tone, all aligned on \"uint32_t\" boundaries (size rounded up to\n *\ta multiple of 4 bytes - except for the last file).\n *\n * \"Firmware Images\" are binary images containing firmware (like\n *\tU-Boot or FPGA images) which usually will be programmed to\n *\tflash memory.\n *\n * \"Script files\" are command sequences that will be executed by\n *\tU-Boot's command interpreter; this feature is especially\n *\tuseful when you configure U-Boot to use a real shell (hush)\n *\tas command interpreter (=> Shell Scripts).\n */\n\n#    define IH_TYPE_INVALID\t\t0\n\t\t\t\t\t\t\t\t/* Invalid Image        */\n#    define IH_TYPE_STANDALONE\t1\n\t\t\t\t\t\t\t\t/* Standalone Program       */\n#    define IH_TYPE_KERNEL\t\t2\n\t\t\t\t\t\t\t\t/* OS Kernel Image      */\n#    define IH_TYPE_RAMDISK\t\t3\n\t\t\t\t\t\t\t\t/* RAMDisk Image        */\n#    define IH_TYPE_MULTI\t\t4\n\t\t\t\t\t\t\t\t/* Multi-File Image     */\n#    define IH_TYPE_FIRMWARE\t5\n\t\t\t\t\t\t\t\t/* Firmware Image       */\n#    define IH_TYPE_SCRIPT\t\t6\n\t\t\t\t\t\t\t\t/* Script file          */\n#    define IH_TYPE_FILESYSTEM\t7\n\t\t\t\t\t\t\t\t/* Filesystem Image (any type)  */\n#    define IH_TYPE_FLATDT\t\t8\n\t\t\t\t\t\t\t\t/* Binary Flat Device Tree Blob */\n\n/*\n * Compression Types\n */\n#    define IH_COMP_NONE\t\t0\n\t\t\t\t\t\t\t\t/*  No   Compression Used   */\n#    define IH_COMP_GZIP\t\t1\n\t\t\t\t\t\t\t\t/* gzip  Compression Used   */\n#    define IH_COMP_BZIP2\t\t2\n\t\t\t\t\t\t\t\t/* bzip2 Compression Used   */\n\n#    define IH_MAGIC\t0x27051956\n\t\t\t\t\t\t\t\t/* Image Magic Number       */\n#    define IH_NMLEN\t\t32\t/* Image Name Length        */\n\n/*\n * all data in network byte order (aka natural aka bigendian)\n */\n\ntypedef struct image_header {\n\tuint32_t ih_magic;\t\t\t/* Image Header Magic Number    */\n\tuint32_t ih_hcrc;\t\t\t/* Image Header CRC Checksum    */\n\tuint32_t ih_time;\t\t\t/* Image Creation Timestamp */\n\tuint32_t ih_size;\t\t\t/* Image Data Size      */\n\tuint32_t ih_load;\t\t\t/* Data  Load  Address      */\n\tuint32_t ih_ep;\t\t\t\t/* Entry Point Address      */\n\tuint32_t ih_dcrc;\t\t\t/* Image Data CRC Checksum  */\n\tuint8_t ih_os;\t\t\t\t/* Operating System     */\n\tuint8_t ih_arch;\t\t\t/* CPU architecture     */\n\tuint8_t ih_type;\t\t\t/* Image Type           */\n\tuint8_t ih_comp;\t\t\t/* Compression Type     */\n\tuint8_t ih_name[IH_NMLEN];\t/* Image Name       */\n} image_header_t;\n\n#endif /* __IMAGE_H__ */\n"
  },
  {
    "path": "include/u-boot/mtdinfo.h",
    "content": "#ifndef _MTD_INFO_H_\n#    define _MTD_INFO_H_\n\n#    define STR_LEN_MAX\t\t\t\t\t32\n#    define MTD_MAP_MAX\t\t\t\t\t4\n\nstruct m_device_info {\n\tchar name[STR_LEN_MAX];\n\tunsigned int size;\n\tunsigned int phys;\n#    if __x86_64__\n\tunsigned int virt;\n\tunsigned int cached;\n#    else\n\tvoid *virt;\n\tvoid *cached;\n#    endif\n\tint bankwidth;\n\tunsigned int used;\n};\n\nstruct m_partition_info {\n\tchar name[STR_LEN_MAX];\t\t/* identifier string */\n\tunsigned int offset;\t\t/* offset within the master MTD space */\n\tunsigned int size;\t\t\t/* partition size */\n\tchar filename[STR_LEN_MAX];\t/* file name */\n\tunsigned int filesize;\t\t/* file size */\n\tunsigned int sw_ver;\t\t/* software version */\n\tunsigned char used;\t\t\t/* Is this partition is used? */\n\tunsigned char valid;\t\t/* Is this partition is valid? */\n\tunsigned char mask_flags;\t/* master MTD flags to mask out for this partition */\n};\n\nstruct m_partmap_info {\n\tunsigned int magic;\n\tunsigned int cur_epk_ver;\n\tunsigned int old_epk_ver;\n\tunsigned char nmap;\n\tunsigned char npartition;\n\tstruct m_device_info map[MTD_MAP_MAX];\n\tstruct m_partition_info partition[PM_PARTITION_MAX];\n};\n\n#    define M_GET_PART_INFO(x)\t\t\t((struct m_partition_info *)&(m_partinfo.partition[x]))\n#    define M_GET_DEV_INFO(x)\t\t\t((struct m_device_info *)&(m_partinfo.map[x]))\n\nextern struct m_partmap_info m_partinfo;\n#endif /* MTD_INFO_H_ */\n"
  },
  {
    "path": "include/u-boot/partcommon.h",
    "content": "#ifndef _PART_COMMON_H_\n#define _PART_COMMON_H_\n\n#define U64_UPPER(x)\t(unsigned long)( (x) >> 32 )\n#define U64_LOWER(x)\t(unsigned long)( (x) & 0xffffffff)\n\n/*#ifndef NO\n#define NO\t\t\t\t\t\t\t0x00\n#define YES\t\t\t\t\t\t\t0x01\n#endif*/\n\n/*-----------------------------------------------------------------------------\n * partition info\n */\n#define PART_FLG_FIXED\t\t\t\t1\n#define PART_FLG_MASTER\t\t\t\t2\n#define PART_FLG_IDKEY\t\t\t\t4\n#define PART_FLG_CACHE\t\t\t\t8\n#define PART_FLG_DATA\t\t\t\t16\n#define PART_FLG_SECURED\t\t\t32\n#define PART_FLG_ERASE\t\t\t\t64\n\n#define STR_LEN_MAX\t\t\t\t\t32\n\n#define PM_PARTITION_MAX\t\t\t64\n\ntypedef enum PART_INFO {\n\tPART_INFO_IDX = 0,\n\tPART_INFO_OFFSET,\n\tPART_INFO_SIZE,\n\tPART_INFO_FILESIZE\n} PART_INFO_TYPE;\n\ntypedef enum {\n\tSTRUCT_INVALID,\n\tSTRUCT_MTDINFO,\n\tSTRUCT_PARTINFOv1,\n\tSTRUCT_PARTINFOv2\n} part_struct_type;\n\nunsigned int dump_partinfo(const char *filename, const char *outfile);\n\nextern const char *modelname;\nextern part_struct_type part_type;\n\n#endif /* _PART_COMMON_H_ */\n"
  },
  {
    "path": "include/u-boot/partinfo.h",
    "content": "#ifndef _PARTINFO_H_\n#define _PARTINFO_H_\n\n#include \"partcommon.h\"\n#include \"partinfov1.h\"\n#include \"partinfov2.h\"\n#include \"mtdinfo.h\"\n\n#endif\n"
  },
  {
    "path": "include/u-boot/partinfov1.h",
    "content": "#ifndef _PART_INFO1_H_\n#define _PART_INFO1_H_\n\nstruct p1_device_info {\n\tchar name[STR_LEN_MAX];\n\tunsigned int size;\n\tunsigned int phys;\n#if __x86_64__\n\tunsigned int virt;\n\tunsigned int cached;\n#else\n\tvoid *virt;\n\tvoid *cached;\n#endif\n\tint bankwidth;\n\tunsigned int used;\n};\n\nstruct p1_partition_info {\n\tchar name[STR_LEN_MAX];\t\t/* identifier string                               */\n\tunsigned int offset;\t\t/* offset within the master MTD space              */\n\tunsigned int size;\t\t\t/* partition size                                  */\n\tchar filename[STR_LEN_MAX];\t/* file name                                       */\n\tunsigned int filesize;\t\t/* file size                                       */\n\tunsigned int sw_ver;\t\t/* software version                                */\n\tunsigned char used;\t\t\t/* Is this partition is used?                      */\n\tunsigned char valid;\t\t/* Is this partition is valid?                     */\n\tunsigned int mask_flags;\t/* master MTD flags to mask out for this partition */\n};\n\nstruct p1_partmap_info {\n\tunsigned int magic;\n\tunsigned int cur_epk_ver;\n\tunsigned int old_epk_ver;\n\tunsigned char npartition;\n\tstruct p1_device_info dev;\n\tstruct p1_partition_info partition[PM_PARTITION_MAX];\n};\n\n#define P1_GET_PART_INFO(x)\t\t\t((struct p1_partition_info *)&(p1_partinfo.partition[x]))\n#define P1_GET_DEV_INFO(x)\t\t\t((struct p1_device_info *)&(p1_partinfo.dev))\n\nextern struct p1_partmap_info p1_partinfo;\n#endif /* _PART_INFO1_H_ */\n"
  },
  {
    "path": "include/u-boot/partinfov2.h",
    "content": "#ifndef _PART_INFO2_H_\n#define _PART_INFO2_H_\n\n#define P2_PARTITION_MAX\t\t\t\t128\n\nstruct p2_device_info {\n\tchar name[STR_LEN_MAX];\n\tunsigned long long size;\n\tunsigned long long phys;\n#if __x86_64__\n\tunsigned int virt;\n\tunsigned int cached;\n#else\n\tvoid *virt;\n\tvoid *cached;\n#endif\n\tint bankwidth;\n\tunsigned int used;\n};\n\nstruct p2_partition_info {\n\tchar name[STR_LEN_MAX];\t\t/* identifier string                               */\n\tunsigned long long offset;\t/* offset within the master MTD space              */\n\tunsigned long long size;\t/* partition size                                  */\n\tchar filename[STR_LEN_MAX];\t/* file name                                       */\n\tunsigned int filesize;\t\t/* file size                                       */\n\tunsigned int sw_ver;\t\t/* software version                                */\n\tunsigned char used;\t\t\t/* Is this partition is used?                      */\n\tunsigned char valid;\t\t/* Is this partition is valid?                     */\n\tunsigned int mask_flags;\t/* master MTD flags to mask out for this partition */\n};\n\nstruct p2_partmap_info {\n\tunsigned int magic;\n\tunsigned int cur_epk_ver;\n\tunsigned int old_epk_ver;\n\tunsigned char npartition;\n\tstruct p2_device_info dev;\n\tstruct p2_partition_info partition[P2_PARTITION_MAX];\n};\n\n#define P2_GET_PART_INFO(x)\t\t\t((struct p2_partition_info *)&(p2_partinfo.partition[x]))\n#define P2_GET_DEV_INFO(x)\t\t\t((struct p2_device_info *)&(p2_partinfo.dev))\n\nextern struct p2_partmap_info p2_partinfo;\n#endif /* _PART_INFO2_H_ */\n"
  },
  {
    "path": "include/util.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * All right reserved\n */\n#ifndef __UTIL_H\n#define __UTIL_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdint.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <elf.h>\n#include \"common.h\"\n#include \"mfile.h\"\n\n#define member_size(type, member) sizeof(((type *)0)->member)\n#define err_exit(fmt, ...) \\\n\texit(err_ret((fmt), ##__VA_ARGS__))\n\n#ifdef __APPLE__\ntypedef    unsigned int    uint;\n#endif\n\nchar *my_basename(const char *path);\nchar *my_dirname(const char *path);\nint count_tokens(const char *str, char token, int sz);\nvoid getch(void);\nvoid hexdump(const void *pAddressIn, long lSize);\nvoid rmrf(const char *path);\n\n/* Print message and return EXIT_FAILURE. (On Cygwin, also waits for keypress.) */\nint err_ret(const char *format, ...) FORMAT_PRINTF(1, 2);\n\nchar *remove_ext(const char *mystr);\nchar *get_ext(const char *mystr);\nvoid createFolder(const char *directory);\nMFILE *is_lz4(const char *lz4file);\nbool is_nfsb_mem(MFILE *file, off_t offset);\nMFILE *is_nfsb(const char *filename);\nvoid unnfsb(const char *filename, const char *extractedFile);\nMFILE *is_gzip(const char *filename);\nint is_jffs2(const char *filename);\nint isSTRfile(const char *filename);\nint isdatetime(const char *datetime);\nint isPartPakfile(const char *filename);\nint is_kernel(const char *image_file);\nvoid extract_kernel(const char *image_file, const char *destination_file);\nint asprintf_inplace(char **strp, const char *fmt, ...) FORMAT_PRINTF(2, 3);\n\n\n#include <errno.h>\nvoid print(int verbose, int newline, const char *fn, int lineno, const char *fmt, ...) FORMAT_PRINTF(5, 6);\n#define WHEREARG  __FILE__, __LINE__\n#define PRINT(...) print(0, 0 , WHEREARG, __VA_ARGS__)\n#define VERBOSE(N,...) print(N, 0, WHEREARG, __VA_ARGS__)\n#define VERBOSE_NN(N,...) print(N, 0, WHEREARG, __VA_ARGS__)\n#define PERROR_SE(fmt, ...) print(0, 0, WHEREARG, \"ERROR: \" fmt \" (%s)\", ## __VA_ARGS__, strerror(errno))\n#define PERROR(...) print(0, 1, WHEREARG, \"ERROR: \" __VA_ARGS__)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/util_crypto.h",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#ifndef __UTIL_CRYPTO_H\n#define __UTIL_CRYPTO_H\n#include <stdint.h>\n#include <openssl/aes.h>\n\n#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined (LIBRESSL_VERSION_NUMBER)\n#define EVP_MD_CTX_new EVP_MD_CTX_create\n#define EVP_MD_CTX_free EVP_MD_CTX_destroy\n#endif\n\n#define KEY_ECB (1 << 0)\n#define KEY_CBC (1 << 1)\n\ntypedef int (*CompareFunc)(uint8_t *data, size_t size);\n\nvoid setKeyFile(const char *keyFile);\nvoid setKeyFile_LG();\nvoid setKeyFile_MTK();\n\nuint8_t *getLastKey();\nuint8_t *getLastIV();\n\n#define MAX_KEY_SIZE (AES_BLOCK_SIZE * 2) // AES-256\n\ntypedef struct {\n    AES_KEY key;\n    uint8_t keybuf[MAX_KEY_SIZE];\n    uint8_t ivec[MAX_KEY_SIZE];\n} KeyPair;\n\nKeyPair *find_AES_key(\n    uint8_t *in_data, size_t in_data_size, CompareFunc fCompare,\n    int key_type, void **dataOut, int verbose\n);\n\n#endif\n"
  },
  {
    "path": "keys/AES.key",
    "content": "# OTAIDs are examples for testing keys\n\n# unknown\n214BF3C129547AF31D32A5ECB4742192\n\n# common\n1F1E1D1C1B1A19180706050403020100 # BCM35230/early MTK5369 and LG1152\n\n# old (pre-MStar) Mediatek\n7184C9C428D03C445188234D5A827196 # mtk5369 - Mediatek GP4 - HE_DTV_GP4I_AFAAATAA\n385A992430196A8C44F1985823C01440 # mtk5398 (a2) - Mediatek NetCast 4/4.5 - HE_LCD_NC5M_AAAAAIAA\n8E32E4608871ECE9B6301999D5155A07 # mtka5lr (mt5882) - Mediatek webOS 2 (2015) - HE_DTV_W15L_AFAAABAA\n\n# Broadcom/MStar MIPS\n6856A0482475A8B41728A35474810203 # new BCM35230\n2F2E2D2C2B2A29281716151413121110 # Saturn7/BCM3556\n212D3B2A5C2D3A2C4D5B234B1A321D2A # new Saturn7/old LM1\n4F836AAEB4301F26172A9B0E1120EAF4 # LM1 PDP\n4EE662C7A2C0917F7328DE73A0836C6B # LM1 LCD\n\n2F534ABE34801A36B7DA6B3EB1C04AD4 # m1 - MStar non-webOS - LN45*, LN53*, LN54*, LN565*, LA61*, LA643*, MA53*, PN45*, PN65*\n7B2CA5943D2E752CF58606228C5B2DAD # m1a - MStar non-webOS (L15 signage) - BS_LCD_LE15_AAAAAIAM\n# MISSING: m1ap - MStar L16 - HE_LCD_LE16_AAAAABAA\n# MISSING: m1a - MStar L18 signage - HE_IDD_LM18_DSAAGLAA\n# MISSING: m1a - MStar L19 signage - HE_IDD_LM19_AHAAAIAM\n\n# MStar ARM\nD55C6864035A8C8A2B35A6D6C4565596 # m2 - MStar SimpleSmart - HE_LCD_SS1A_AFAAAIAA\nADB92D9E23035522F4708CC259B31EA2 # m2 - MStar webOS 3.0 (2016) - HE_DTV_W16R_AFAAABAA\nD2E6EE17639DFE2F81D3840FA0BC334A # m2r - MStar webOS 3.5 (2017) - HE_DTV_W17R_AFAAABAA\n4F6DE80C0362FD562464BC2073D15567 # m3 - MStar webOS 4.0 (2018) - HE_DTV_W18R_AFAAABAA\n88723D91920712D0BAFE87A25E6E8EC7 # m3r - MStar webOS 4.5 (2019) - HE_DTV_W19R_AFAAATAA\n68A284B4953CAD15024BED2C4F852A09 # lm14 - MStar NetCast 4.5 (2014/2015) - HE_LCD_NC5U_AAADABAA\n19F51EE9B949C89E41AE136F48BB405C # lm14a - MStar webOS 2 (2015) - HE_DTV_W15A_AFADABAA\nF8F6BD1AA24506C2759E1BE1D51BB43C # lm14alite - MStar webOS 2 (2015) - HE_DTV_W15B_AFADABAA\n96F464CB29CDFF5441FD87D47D084FF8 # lm15u - MStar webOS 2 (2015) - HE_DTV_W15U_AFADABAA\n6FCCC4AA3389B614BABE462498D2020A # lm18a - MStar webOS 4.0 (2018) - HE_DTV_W18A_AFADATAA\n806B982279521809DBAD9E2E6BF377763903565A7EB4604BAB1E1503DBFC4326 # lm21a - MStar webOS 6 (2021) - HE_DTV_W21A_AFADATAA\nB65119E0E6CB5DB19C69B4CC78FAC3A87C747E5AEFDE8FF58F2CD47128D9E16D # lm21u (mt5889) - MStar webOS 6 (2021) - HE_DTV_W21U_AFADATAA\nFC9D81DEC206BA62614C949C43D2DA91D23E9FF3DF9674D69A444D13277BDF96 # lm21ut - MStar webOS 6 StanbyME (2022) - HE_DTV_N21D_AFAAATAA\n3435663331313732316538383063663538306161643131653335323334613034 # lm21an - MStar webOS 7 (2022) - HE_DTV_W22A_AFADATAA\n1FB2C3B789D5EA48ED16E79A0343986C691DACEC872BB07787D0F722AF5D1E2C # lm21ann - MStar webOS 8 (2023) - HE_DTV_W23A_AFADATAA\n\n# LX/LGE (GP, NetCast, webOS)\n4813B5B63C998A2874EF3320684AC8D9 # lg1152 - LX GP4 - HE_DTV_GP4H_AFAAATAA\n14B3623488212250C7C992AACD537447 # lg115x - LX NC4 - HE_LCD_NC4H_AAADABAA\n12C344FDD2871C983CD0FBBC25143974 # lg1154 (h13, goldfinger) - LX webOS 1 (2014) - HE_DTV_WT1H_AFAAABAA\n34CC219D3AFC102433109BBC1DA44095 # m14 (m14tv) - LX webOS 1 (2014) - HE_DTV_WT1M_AFAAATAA\n5A167D8C342EF094800E7CFA2D10F2D0 # m14 (m14tv) - LX webOS 2 (2015) - HE_DTV_W15M_AFAAATAA\n13F56BE4B4A0829598DB8F74065A263B # h15 - LX webOS 2 (2015) - HE_DTV_W15H_AFADATAA\n# MISSING: h15 - LX webOS 3.0 (2016) - HE_DTV_W16H_AFADATAA\n3679EF1840B7FDEBC1FBF95A0CAFCE3E # m16 - LX webOS 3.0 (2016) - HE_DTV_W16M_AFADABAA\n5804DF78CB8DC6A71C05DAB0F1EDE3E1 # m16lite - LX webOS 3.0 (2016) - HE_DTV_W16N_AFADABAA\n1B3C76ADD3F5EE6B089DB253747A8CD4 # m16p - LX webOS 3.5 (2017) - HE_DTV_W17H_AFADABAA\n3C9D30DF3A95C1AA41928813292BD947 # m16plite - LX webOS 3.5 (2017) - HE_DTV_W17M_AFADATAA\n# MISSING: m16pbno - LX webOS 3.5 (2017) - HE_DTV_W17B_AFADABAA\n89E11D498392F5A521145738EF036AE5 # m16pstb - LX webOS 3.5 (2017) - HE_DTV_W17S_AFADATAA\n437C02F0DF99F2072D1A64EEBBD2953B # m16pp - LX webOS 4.0 (2018) - HE_DTV_W18H_AFADABAA\n3471D9BFC5F4B34A8997D56932F34D94 # m16pplite - LX webOS 4.0 (2018) - HE_DTV_W18M_AFADATAA\n3FE1CBE11BD658BB37813E05052D5FE5 # m16p3 - LX webOS 4.5 (2019) - HE_DTV_W19H_AFADABAA\nA2FA48FCC1A22FD2F1944BEFA8403765EF178D4F4AB0E81AC7B5B267ACBDF14D # m23 - LX webOS 8 (2023) - HE_DTV_W23M_AFADATAA\n\n# LX/LGE OLED-specific (webOS)\nE529BCDEDF8E49667C0FA3A81174B65E # o18 - LX webOS 4.0 (2018) - HE_DTV_W18O_AFABABAA\n4ACD2CA8425BBA6C49FD03A174300239 # o18 - LX webOS 4.5 (2019) - HE_DTV_W19O_AFABABAA\nC9EF645424A625BBAE7521394564025EC6252658FB650D33633111BD40C76011 # o20 - LX webOS 5 (2020) - HE_DTV_W20O_AFABATAA\n944288798A122C6130B661BEE52DF4FE42120F60A61E312DCFC1411E300A29AE # o20n - LX webOS 6 (2021) - HE_DTV_W21O_AFABATAA\n3861333237633238613136633438663239623238623037656335623433353862 # o22 - LX webOS 7 (2022) - HE_DTV_W22O_AFABATAA\nCF5D6DC934F18618B968382368E17BA971DEAA2ECDFC906874B327D87076E228 # o22n - LX webOS 8 (2023) - HE_DTV_W23O_AFABATAA\n53D6DC79418C1A2371DC9F926CD3A3A06F4E7E4396464B5F41248083C2C65637 # o22n2 - LX webOS 9 (2024) - HE_DTV_W24G_AFABATAA\nB7724DBBF2AEA073131E8E7D62D114E2AA02F99D17CD7350C14466624528ED79 # o24 - LX webOS 9 (2024) - HE_DTV_W24O_AFABATAA\nFE90B0C1BE8CC28A9738333F95AC2C58777BDE7D4E8CABABA73B24FB7D1781C7 # o22n3 - LX webOS 10 (2025) - HE_DTV_W25G_AFABATAA\n52A208FA24E7E70730A40999B1C22C148F4920484BC50B515D243E35D14689F1 # o24n - LX webOS 10 (2025) - HE_DTV_W25O_AFABATAA\n\n# LX/LGE 8K (webOS)\nCD4171FC9C06869627A67EA7B66D739D # o18k - LX webOS 4.5 (2019) - HE_DTV_W19K_AFADATAA\n0EE52A12A2EB5DE2E13999187B14913F6D3367A79B39AC35979A51E5C12A4FDF # o208k - LX webOS 5 (2020) - HE_DTV_W20K_AFADATAA\n# MISSING: e60 - LX webOS 5 (2020) - HE_DTV_W20E_AFADATAA\nE27E6AFE44B7866D60C24ED27904ECB296CA69B4251478B5248C03851F08ECF5 # e60n - LX webOS 6 (2021) - HE_DTV_W21K_AFADATAA\n# MISSING: o228k - LX webOS 7 (2022) - HE_DTV_W22K_AFADATAA\n# MISSING: o22n8k - LX webOS 8 (2023) - HE_DTV_W23K_AFADATAA\n# MISSING: o22n28k - LX webOS 9 (2024) - HE_DTV_W24K_AFADATAA\n\n# Realtek (webOS)\nF2B78AEBAD6D86A17B4742B2B84B60F4 # k2l - Realtek webOS 3.0 (2016) - HE_DTV_W16K_AFADATAA\nC2FBBC5DDD9D366B7FD6CAEB90F86039 # k2lp - Realtek webOS 3.0 (2016) - HE_DTV_W16P_AFADABAA\n1C966DFA0E5AE9946AAF8D2EC06B9E18 # k3lp - Realtek WebOS 3.5 (2017) - HE_DTV_W17P_AFADABAA\nAD17A5923B525FD21DB765A5B6822FBD # k5lp - Realtek webOS 4.5 (2019) - HE_DTV_W19P_AFADABAA\n388BE4B04BD98E7C3CA45A4C6CA346DD2EB32BDCD05DC28FC4A87C9625294A5E # k6lp - Realtek webOS 5 (2020) - HE_DTV_W20P_AFADATAA\n377050F9B9D91CD803ACAACCEA4046DD99B01CFBB0010451F4F87A1620C4BAEF # k6lpfhd - Realtek webOS 5 (2020) - HE_DTV_W20L_AFAAJAAA\n395324AD369A529EABAC71FE1E72C25CE25594294D47303BCB2629241AFA4C98 # k6hp - Realtek webOS 5 (2020) - HE_DTV_W20H_AFADABAA\n74514676D68B9A72A0093CEF56D3067484E1F4D5CF7D4B4ED389BED030FA1B09 # k7lp - Realtek webOS 6 (2021) - HE_DTV_W21P_AFADATAA\n6A42D2485B716B25AE5C9921176588D167C25B902D4EF2903AF5C1FCC61D34C9 # k8lp - Realtek webOS 7 (2022) - HE_DTV_W22P_AFADATAA\nA35A57DFDD8266F7CE1AF991EC67BABF6723653ABB9A7D48A4B8AB2A2485BCFE # k8hp - Realtek webOS 7 (2022) - HE_DTV_W22H_AFADATAA\n703373367638792F423F4528482B4D6251655468576D5A7134743777217A2443 # k8lp - Realtek webOS 7 hospitality (2022) - HE_IDD_H22P_AHAAATAA\n6251655468576D5A7133743677397A24432646294A404E635266556A586E3272 # k8hp - Realtek webOS 7 hospitality (2022) - HE_IDD_H22H_AHAAATAA\n3764336361633437326166373639383663353863363039316332383031626637 # k8ap - Realtek webOS 7 (2022) - HE_DTV_W22L_AFAAATAA\n64E629FDD8B7BE4A3D4ECD85F1BFCE6FC49CDEF32CFFB16B4716A7BEE6F3B258 # k8hpt - Realtek webOS 7 StanbyME Go (2023) - HE_DTV_N22D_AFAAATAA\nDFFD1E4F093E305451D4F3752E63BA9A3E6A6404922D986DF36C00818F5595C1 # k8hpp - Realtek webOS 8 (2023) - HE_DTV_W23H_AFADATAA\nEC2C89B4AF45B5EB7EA9A83DD2387810C0815BD31BBFE1D17C809E7D68339112 # k8lpn - Realtek webOS 8 (2023) - HE_DTV_W23P_AFADATAA\n90A21E96D39A933982B7508E59272040DCA34EB4782FF289D1AFEFEC0C68590C # kf23f - Realtek webOS 8 (2023) - HE_DTV_W23L_AFAAATAA\nF322A9CA1D523C358DD2FD97D5660E25386C9C60E423632AEC9723D282BE971D # kf23f - Realtek webOS 8 smart monitors (2023) - HE_MNT_S23Y_AAAAGLAA\n6252A0816884997B2FCA30662561A721A4BCC40B18CBEA5D363FA844F17D7DE9 # kid23q - Realtek webOS 8 ultrawide monitors (2023) HE_MNT_S23Z_AAACGLAA\n7638792F423F4528482B4D6251655368566D597133743677397A24432646294A # k8lpn - Realtek webOS 8 hospitality (2023) - HE_IDD_H23P_AHAAATAA\n6B5AD1BE81D7A1A494F58EB659431850C1B681826EE4428394D4897052691756 # k8lpn2 - Realtek webOS 9 (2024) - HE_DTV_W24P_AFADATAA\nFA9EBB838B7BAFBA75EFE8D5A3560374EB0699A113411CA924051B4ADB52E10D # k24 - Realtek webOS 9 (2024) - HE_DTV_W24H_AFADATAA\n1A8ADAB21D9FF995677DB32BCE2E0CD559AE86840EBF4A696872076E37DFFE8F # k24t - Realtek webOS 9 StanbyME 2 (2024) - HE_DTV_N24D_AFADATAA\n25DF24166745B52EAB661455BED43DE376320FAA1F7824877B938DB869308B18 # k25lp - Realtek webOS 10 (2025) - HE_DTV_W25P_AFADATAA\nB2E8C3E214F044B823916E48FA074E606C7C5CD5E6902B6F99BD903DAC0C792F # k24n - Realtek webOS 10 (2025) - HE_DTV_W25H_AFADATAA\n\n# Realtek WEE (webOS)\nB23981FD3642CDF401E7A0C2FADBDA4399B6AAF9600B802144933B4F4E5855EA # k6lpwee - Realtek webOS 5 (2020) - HE_DTV_C20P_AFADATAA\n3263653764623932376235323637653637633035363066353833303235383466 # k8lpwee - Realtek webOS 7 (2022) - HE_DTV_C22P_AFADATAA\n46715DFBDE23C2D8CBA7EC4F36BA41AAD28E7EC00FEC51F2843F24654DB09BD3 # k8hpwee - Realtek webOS 7 (2022) - HE_DTV_C22H_AFABATAA\n6238323334663232396632613762316537333731333832306664666136333564 # k8apwee - Realtek webOS 7 (2022) - HE_DTV_C22L_AFAAATAA\n9E8D2BAC9DCBEFC878CC8203431A70E00C2122DEF82FD5099D04BA259B1B2E4B # kf23fwee - Realtek webOS 8 (2023) - HE_DTV_C23L_AFAAATAA\n"
  },
  {
    "path": "keys/MTK.key",
    "content": "09291094092910940929109409291094,00000000000000000000000000000000 # Mediatek Generic (Hisense, Sharp, Philips)\n53686172536861725348617253686172,00000000000000000000000000000000 # SharSharSHarShar (Sharp key for Sharp external partition)\n5450565F5450565F5450565F5450565F,00000000000000000000000000000000 # TPVision(Philips) 2012\nD378EAF81D378A801B556985789A7C31,73079FD19183715E130858588479C652 # Philips 2012\n47FBF8CAD62BB95AF3AD9509E5C2175D,63120FB321B0410F216D6DC2D8641A11 # Philips 2013\n55555555555555555555555555555555,B1BFAA407F70C80C650379DFEAFAA40F # TCL 2017\n1B569AA7D2E4CCE66584A7A3D8A45679,A0E88D5D52A813260D3A34A14AA89416 # TPV_MTK2K17PLF_EU0\n135AFB6DE91CD56496244BC7C0E08D63,C6A38C89F0AF5637EB6E19D35E12E257 # TPV_MTK2K14PLF_EU1\n7B17F7764818AE2C897BA69D428D0CB3,672041CCB9FCD4272B11E57AB6047163 # TPV_MTK2K16PLF_EU0\n"
  },
  {
    "path": "keys/README.md",
    "content": "keys\n===========\nPlace keys in this folder before running ./build.sh\n"
  },
  {
    "path": "keys/e60.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3pE29z9xS/7WmMScGR/q\nm/o7S3kN6vmuNgb9XjItG6K5z9sGmtyvvyBbQGe62PI2tQ3/sFL3seoR35cKyqCC\nSYdV0kgY+IEc/u8+9r2B+k5WWeGRkUXUkqDPXBtC+kNkDRg0PkavGMJcxhOzP2HR\niPFYv2pqlgq7PXD+BrfGIcvZShgUnPcufuQkqDmR/BF0DAYJMbdmn8Y0gu9xNekW\n5odvC31dGMss2xR/JCh32PeYoVv2+v5M29PhXlpDoDHlUeIuKp+TLajd76p84WSd\ndCRuCv/HIjBNBm0ip4K6wp1388HfXoG1ZMquRykiMnjR4RlkMOwlZkzcr31ovRN4\nmwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/e60n.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvFix6BZ9npNUCNtzDDK0\njXPukBfR+VJ5tj21pq+R4YUf4ImrKVre+onh0/bCsJgEVAM822d7BRCGRytHHahB\nypBd9e+yCFQzIQLVpM4MRiy/SM/xq0EcHeVKg5phgAxV0cElb8MKJ3Q6W5rqXi9B\n7o9Q7fONLFAocQR7WN69OWhT72afswkrfuat9JAPtn05NgZ17UEbWzUzBDrU2uWw\n5x5bFiUX5qHYeocuZK2Nn5n3q/zV7EyaRCgqbWBDb5WcWrQBu0QH+tmCoEiv829g\nhZtkrXJYiQxoh3W8rVqkwGzIE01Ci4yBMaYFRnxkAhogYV8uf+PuE2z6kNW+NVsl\nuwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/general_pub.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6cC7osaLYH//AoKB1LRSrtSVA\nxQ2335JyMhdnrGqR/xvJV5tT04qhzcWjx70FX0wW2xEQbNCouucJoDwcaNvRW2bF\nonNF1oiqkrJLWIhr8DYY81X2Yr1GddLgCf8S3EjJdfkpuWIn22/NIjJZPaEcidx2\npFAqFUk27yT8IkPnrQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/h15.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBc5hEow2FPG39zb01yc9Y6qSR\nq8c5oc/MxiK6xEFHNHEuDNLjYlPxuvdb+I3l8rgTPNMQbwIN4nYpkY6H7q/Pmfan\n3tk7uuVzLNkstc+kYKgM2UxzVGh+D9GDphbIgalkYRFMyGQt8/SCXaVvtdkIa2KL\nDe4gG+WGc8QLiFRxdwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k24.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwLZOuhlUJ18bJO7Psuy9\n82Wf6b0k+JRc+H34HUiFeQcdZfHz5BL5ZqC/vCAt5LwrQuK/rgA2XLZa/fg4HaaR\npcxlX/j7d7HmG93KyRR3NX6EsVts9CyDT3HMEvila1sBfpj1NScjBu25jguYOSr5\n66P5ooLRwpM/yZAJzEii8isYysqcefxVL+VVKBv8HgaCcK2oAWrcEAGiLS2xvRXX\n3ref/3BF0n4ZgDfzXdn+8kqBpGcNpwDmy347jtJAtgddE4d0gQaVr4YYn8mkR9tf\nO9M3ymo/IEtN9z9I9rKicce4ushOC1K9KZV64yZMUGx+s2xLrRbhjIkktF6O9PGg\nGwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k24n.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv/jTYXIo3u/Z9+lF6wt0\n+b7boSJiOGuNMW1iBhkCQ5EkQIT28BkOPodOIOi7ofZF38rnDKdNU/dbmu0qt4Of\nIFL3eO0Wq+mMCI8Hi7Kb/5h59GW5V1wN0Xip6wbaFyz6tJ0jwMhcQUIi85QyUmJ2\nt11zOXiXCGFRC4LC84rvteD799VxtcUgrQKYIhS4UYym0cViIt5Y126p9e63Qlx9\nYQZ7gWWVRIc+dNpY3oGa9rpTTRWoVx8HFmWH7mNRX39uSSBNcK/LJuiibS76fQni\nHll/kB0wsm4DSek4td7gk1hZHb4N59osJM+ex8PYXJMugWBIT8ebk33ygMU+Z1kj\nVwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k24t.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5BL+M/GUNZXNWQKXQk9z\nj9sGxiu7nNvaE8MNQaXE4IvgpgKNGkJPnqX1+CG3d411Nt9h2ms/ofrIzyNSb0C1\nnsnuQAFLEuUnLthsIupXwYPEJf0ORNpUe9uoAG0+Xm9ArPPETXMPFKZviXDRVHpg\nXDwUkmy3jSjI4hXQAFTXBtw6SmHXph8NqJSwl3W7cTsL8B8n1bsnSRTzueaSrrS+\nbToNy1+7ptHu0Yc2s5Ttgz45YqSjWhZbPvv/9fQrIe3qGhrE1wUtoJGkrw7xsX5v\nn/jQ32hZp/xWSQzF2OPWlBgWBKR0fX3Y1dXk/Syq2t7N75Me3hspdzhkni+EX3Ye\n7wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k25lp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0i/S5OoP3jXho4xqWOl1\niLwlY6VT1IUftj0HPIFw+Qrjj+YSxlJjkCA2YHOzA27pC3ICN0PefF0D3uGMbrnM\nN7YaHWw3ph46q4yCqiHND55eA6VeKyf2npIUwUx1/pEszpy1lQIZbY66FR/fqfTW\nLiZL5ioXH50phsvLfk3Lgn49qK94A+z82jcg0hOiuiwt0lXmb2gctxNf8Z69O2Jr\nQN9s21o92qnPoXM7eTfJINrN3jNHYKiywj3CuXt1yAjz6rasYr6EExBtmT4opNbH\n/c7jpeOFRGIacdYLnJhTe13xB9cIWQNJXF8nYwNJKxu04eqFfmmfjfn5q9unxsTg\nDQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k2l.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsNSLkOElA4UKtRn7Qsp\nYgj/LK8q6aRJMPxsYBd95D5ke19g43y2RlFR51vIlzcaEs24a+yKR9jr8MJqagfa\nqU0BXyaTmlSogANqKEjug87AjG1aNUeooquZS96k/2YfZ3QszRJDTWV0jfIKq0hY\npjrYRTvkScQHdtStLlBIlP27WrCPf4Z6DS4xS3l4IGZZC940W36alpXciBAwV9y8\nZ0rqkVnNWDsJXUGeMPfmakdFl498SeidopHnTalxL/DdmtlxMFjI8PfmMTutYyWJ\ngkx03Mv+fVv8Fb+6kFvzCV4fbFd53rQ69eGcXwGXkaVJw6LdO52pYiZhTsqtm8Gk\n3wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k2lp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwbWxWkw05RXCaq/HQO81\ndPH69hMfnZuoACcLzALdQPm8oqxj7hCbtT5+S1GgzPRaQ6ZmiE0zM5U/89wdYOIR\n0Zpb012fiwtZDaH7wWodKYJxCQ+BkSURKSPXutFAKSvWKuy58Bjf8BqT8b92WuW5\nMb3IYv2cvddfrsew/UmRYswyDDzMTwLekYhwFxokpDmbwGm1iLckBji7H/l4OfOZ\nu42YN4gC5lAuT9wKyz/ugwaSYg3A23bd8lUe//ebjetCYmOLuLpOdoIJZIrtG6bJ\nTTEmqlLSaYZQyYh9kD0yORd9xLe2a3/prVFUSL1QeE8h17/ypO6dXoVvXfGFukOP\nKwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k3lp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAum5ztLc/35cYpt0b0D32\nZe1ybhcfWbX9T825QDPE10ifscpP2PFhGEPqbtYi/9X9gLrXK+zMo1Sy04SuPrlH\nbMwpyKv2RKNrmJMneJ6SXMne3MbWzp3E41umjhHhlDZgvyIDFoExTrKlJYroHMG0\nd6PDuE3Em8ReOq/pSQgQ2U4ch0FUeB1Qve7bYUf0QNpE1maMSF7/UD28ZcyP86NB\n7lkttmlY01etIf9D/aATzA0p4kixetl2JlhFqKlNnU0IyUnnL3TPQogmNFYHZByQ\nANpJ7GbVUnbNBuiqYRt3AzZIny92UWZi1zBgwvAUOMJGs4Lvx9/AOOm7fe40ly43\nVwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k5lp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJHtUEdVgac2azz1Vox8\nXZ/zz7aidg0GdQb7jJlUg/Juzce63ZJzKPb8UWLsn60UyMGVYdhx0C+PlzNzbQCP\nlnWQ+D/Nb2mG1Rm6KKULaOjwiwTY35fbwsJ/TbKzdCSvKIzhUfThz1iU1e8f+b67\n3FQVON6KPCV7LH0E8WyOKdP9oPhlVFcMaOtQcU5AYqIbJPFtPBhDy4ACtIdmDbwd\nYKoAs6Oh7GfMUOsaZ9P0Tj+jc5dWTCZyivjirrTf0rAoeOGbCQTwHjuv9+JASnVH\nN8CXdyicr1y3lo1JODWioz+fW4dFOXHbd81ho478MiI1dfiIjPg+NJU27LsVj5lz\n2wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k6hp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAraYnQnvLAx6FSUtZFdQN\nTpevqZEHW2uecg0lD29EeZtjRQOo5z6ukRjXVc3ryMdEVPJjMyTtzOVuRq3XwrHW\n7COXXjENb8hO6oMeilBp+AX3DpJnnTeyq1HYW2Une/EgIM+/+YdclfFZJn9VSg45\nB5uF+q0X2fGLq5DJL6ZR3p5Bxebid+gZLbJcBtWxyO8LJ6NpEo6BS+nLcHrL5f3L\nsGfomwYcU7iHYj2j+8leYdVCgSLEV1q5uypxUCL2n313oMozgLYN+/f0Q6M+d2PN\n0r2uwBq4cqK5IRmw+wpnzhuVO29W+s9gjXD54ipAowmV0W67aa5SmDmB5MHKTXLF\n7QIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k6lp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA22/3Vjzu0ugJ8pqi7qBN\njxYKOOWXMc7QuV1nLxPQJbYP5hqsutZtIBNbQagx1IvE5Hb55qwt6pCtHdmzsNzY\nHljD5BHiZl9hNRy45ViYJpLGzv6LYvoSVRGr3uQe4xSHj/03Yz/FpVkl0a/ICR+l\nHUjlQW8xoy2jZHh2nWSw20cbhc2+cFo4+VBEeX+vzK+/TYytaTS8VJgOIxGaNeXd\nokks4n8wz+snK3a5mI38BGIgBjS2uZmi//IBOsmRlbs3fqP3h6/KeX+QLyzH+TN4\n7sUL2NTEAfhNxG8vB44kRZ59/DLvIKhEka3ofszJ71oGrwvY1ShLXBrQvZnFB35R\nIwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k6lpfhd.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAorYkswYwAHhkADI/WHX9\ni3kyA3wNLofMLCowgDEA4kAIYiKAyLkhw/92OdkO25AytPe7Y/iRxOPtxLXCVsTb\nDcX3NY0235yUzUJwaFeAxRqqFi1g2me87/lOEO/QRe+tZwUHJ8qjzueXflKttK6F\nVxRIrGVjawP95Tiv2HXlCntJsujgugmjsdS7wIrPfC12tsN+BqYKa2kGDaRcuMmM\nWqJeIZ5uQDTkrk5oc37hH7L57AECcIzUwQrDZ1UZdq3XEvXgYvJIhR8+oIdCTQ9c\nOoUNYfWIdrLCBs+EOFY/Ye9ejlGQ/CmBEvRCK8qWdduYNc+wUKZ84ideCw+Rhiz2\n+wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k6lpwee.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyrIvtRFT4n0WUgofQ1wY\npwpmKqMu51ga9fc/d8xygJp90DVDg6+3ELngeoe9V83KWSx26hGcepIwx9DcCQG1\nZvWAqLaCTexeaArA4lqFJUnpAuvyfSe1cbHZSDzC8iXJIjKjpU8A17/3juIIyexP\nhXqMtaiu0RycqAO8wSz5V04sQOstNqLH320OkGvF+vfTkDPOuJM9l/8YWa0WVKEa\nXoovjBGgyS12nOI/2wqFfc3+pdHfLCNnIbRy139y+IyDnYOtS5n7VuCItutUpfg6\n1XTjjRZRXHbT2vqosh2yTCqwJuTxsL1LtjtXlj7NoQ7JeJGid1R9huQQoeI6fdTC\n7wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k7lp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoy1elAjV817rKDn/XHP4\nMc/+SwF4AMwLrypz8XvPcMkJzY4RWu1P/pAlToiQxaZjKYYkCaYSotA8spk/lcoO\ndHTIb1Sn+R60Dsg2hhAC8fl7Zv4evGtZE5fWJR4ciePzBUVadxqgYIcnnYU/VW+g\nIMDcL8CnQsaP225RD6nGte78C4u8U/FECWOs6lauAsrNzAmG/qMNgukaIeiAVaK2\nXW6xECCBjPmQdsU8wEf/RbzJvtPg5mfUyUSlHzUzz86XQ05Z68VZ1ONkxemH6JlW\nSI8XOyOJGhkU728v0i/ZWB054RSSP6NvY7UcV2sNRGnNHGYc2LwFmpxyGaFYZzy2\nMwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8ap.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxtAEdg21wMUIoQlMkgG5\nhRzL+4ygqRD5rzNjMSAvMBSg74v9QSCf69eYkMiObLh81ivLFl/By6+fw8S5JXKU\nSnwnjMvKp5YhMAZ8PrUW0txIHLIoiuVPRIPujrgMPo7o7JQINSVkd3y9LgF43iGA\n9YEj7ufvst7vLTgz3w3H2PYHLxDXod5lJHaKbEvhLqi+YAOdfDQLmAsQY8y+fwUc\nBhlNpNTIAOj0hXdhTBmWo6rEvedU9u2o0pa73NOlp5rdqAdZngvGUMmqqOka8lPq\nlu3kclaU/xdCWrla6xYLoXLPSCppoExRESYEYFxJJMUDEQNr5cG8BfntEPyrzMhU\ndwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8apwee.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzjJEGvo2WtRM9dXNKLzt\nWxz7b+RTZMI+W5odPdehFg4BSmre1kN1MkExk12KNnVE1q2Wrl5BvnYc6inW90gB\nNoOS4SjhXQZQnbQIXhQpj8atTkef8bB1LZY3s6rVg+JvUxibp9aJpc0hPZbqJJBR\nR/HAOZSneAL8LGyf7N/EJxJt3+Bo59glpwdU2T6bkoT22HKrioMxiA4jeTxWUTB4\n9UfwgcHzODGo/cHVwE+gMtdxoj8XTVJblK8tsDq2Xap3vtg/wRcBUhIiAW35O0bW\n7G6YRMrwjhdk2aQf9myu9mGNriAbYWeQ/mZL3+Q1oheFNU1TNIL7ge6aeckEoEsA\nqQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8hp-hotel.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuyyswa5/CCR1+MGKFT6M\nYM9r+uNWig3SmHiFeJwrGl24JUPuRnUcXWNs3fDiNkakDemRrp2cyqGVnDKcAS4e\nDVBARC7YGLTj2wcYS9hQ1t3H74brfz4CtGd+WcaivngBIDig7x0+s7MPQ+aRMSv0\ngyaCqsHLdqrktkhAWyIpwM/73S5LKtaDesB0KdTxS1VqXemqifuoD2Zh/V2GFEW2\nvZytjggzndkE2of7Ay+TOG9NPkDnLB0jlbojOG18GEhqgA5KxNbKtTMY9SeqtP0m\nptljh8awGf4whvYTk7bHnlEJncj+Xe0uATyjlqpulwuNQ4khIRAygiRwQxLRkYNy\nvwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8hp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Hjzub5HrR1OhHqrE7fN\nH3rL/GH8pAeYZZDvPNyrBiZeoBSoVULCYbVhbs1ODKG+Kb2W3FgDbRfr0m2eCGdX\nDZ1KMR5LWpmvCClZ8cz5OGuGFYjJh36pGTa2cvvWB2aMbjNkIaVuIgPSyZBpR6S+\nWaEXeh3IQVPLAlCXgEGscvNDJpF1dv90NFZwtvKIioKXzXKjNk0Y/AUMHNHY7qS6\nBlk4mbobtooEpe2/MhtPMrkKBpqr8poRS13cKzwQi8QjnxNqm4BpdaHkM7hKTRQs\nnzA/prVLM+OLsShKJUJ7K6Hr0ThoFilMIXcolPCLQV+hQh+T42zskEXPcDr8tDAu\nyQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8hpp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2MDSxR5OrlAXB48c7i0U\nFAz0fRKoy99oKK9J0s01tWhrO3aum4NKCPt6nMnmfdImFgxZBG/K1tN6Eo83dQ16\n+6cmpTzfiZKvyMdJAZfuS0wwdvZsPjtQZxgWpgBKKycWUcfxmev1eCTgkeauxKPC\nZpNmyiYmrWU5hvAboT+q/EqNiwdvCiVxtsIlu8f2IlrioFglRKCBmcQPjKxWAUF3\n7lOG6iF/m2MSBBmL1p7qKXj0jTHobnSOvmWHCIJCkQdSunNr+QWgkd8aTHp1ydso\nMxOOYE8xGgaqKECextyY1IFO2eY0lXQo3FBisVTVDIvFXYWln8wclZHA1L82VXR/\nrwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8hpt.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7E0eMvzsQWEdQGd1yuRQ\ni1HoICLdxX9e/cuOia/C347Lk5LLV/sK2GAhalHHi9KZCiPl8iFZiwSiOurjeecq\nucTws4wceStHWH+Ol8I2yKBagC5Ls/herv/IXlys62hzSR5uZydQvi0hVzSDbtWL\nxcfCTEdCiHcpxem9fR9+KJmiakX1KJxT22GJjhCjsZ50m/QTOYN23T7vzDmymJ/y\nTXzM8lbgya9yoYYn6ryZ0XRaRf0pZ1/lEQiKKi8p75d3eSxets5Jh5xEYlI5KZom\ntCT5hPLOqp0EMJ1ctFV7n0XLMWW0uREbaRwzXatH1yiKit+0DKnvpqA/5O03Nx0v\nzQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8hpwee.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0YJdfY4oum0tMLj87Hw6\nYCYRg7Fcjxa6W0PzDyR+9kYAjw+Uxm6aYjQ393gkJXOuex29VxEUkEVZG5hNMOLa\nMYuqrT0FnFRfFL6Gg4ABNF0bFvgGfwwZPS/dBOIw2PIKyWYYR/4sV5JF/hrWwApk\nlx59zWMz/1eC3JDSneeYtbrBUIQncRREt+IsBiS8PP3iI1dMMjbw4kn3WvNIwiwt\nwXUf2WVQuEmdoCikl9PigOEGydTpIL0ACVVcJ7RSwKd6lq4XGhjyDrS2E1nlvdsR\nWT9uU4f1rET8GGEjCHg8XD2R8vNGPs92ODMMW3kOoBucyDNUmOmWeBzjsyiwg41P\nKwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8lp-hotel.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8KDgT0wlg0ewQE/9Wok2\nudDba0SaCzahjnliI/u8KZekWmMg8SaXOpBEaawh7yQmLhUCQ3pnWoAKklUyYJKz\n8ELpen04FJ1gohJTY0KyvowI5GoqsxbxtbyC3MzP5bAst1c+eixk80KVjhXo/lRv\n0cx6FIqC12TEoMPKIsxt2ADhmCZYhGemrrVTmUVPKcmUujp4ZC1VMcPURHZBqUPK\nBQrOj3/UB6TzRS9z04Dcs5BTXhhPpdaYbD/ZYF+z3dGiXLDNh+Xy7+W7ZgRanBvP\nyKqFUAsrZ6DMHp6EmC3eTY3WNEFbhB4fX/SZt4H2P8GpVoBV/EoC+TaeeFSi9VLX\niQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8lp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAngeMYnN8sMfSeC0yHSi8\n5vjv1TAscgAlXdAZFyr7FAjDyqDfjPbS5qVFBicQnr9C67eUvNwIsiKqB+lvwGhu\neTmO3dDQTlWz/TABaWHZ4LfkGEeTM2JlTgy41REFBSv8v6YC0qYmTV8Esd7ZAxNn\nJ9pHkMEgFznfFxG+lEF3kPoIQEIaQd0wRzDrLg2FF4rXR/SwZ5PpSFFAhIEUYwM6\n4aofzCAbziL7qugKrk3Q3sysO6MDPIce6RBhpPZy9XgCXs2vuhF6493W+T/NK204\nxyBrNG/J6dfu0UWUbulZS7tvRB0HD4mmFnoPYu90UxifmWmBGLt0saAai5azaQ9s\naQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8lpn-hotel.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvPBfk1NJ8kSGQp1s1vUK\nPlo2HlPBoxwmQ5I2JJ0SGOWzU7zv39L+42ciNpxazhHKzDbt54ciTbOWAHw4f/qx\nvotGIhfHE5Zx/NTfDaxvEDM53eTrjuJZWcu0wRHZmPOza/+X49ZlHNrN97UWEsDs\nuZinBBHtJGRncBjpjaszE/cd+Z2Z7ctIU6H6iPhs7jg3y24mkfYKp+s2xDeyvo2a\n5jO5XO80nCQLTnF1JGNHnnHz2+K51W9WttNUBpWr9K8kiJd1Y4yrK1WmcohOGNVT\nSPOh1fZyrZyTLwNDHet7DFWMJVagoyEGH/T1bI6eOKPILfx5mo92tZO/VhDr7dtu\ncQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8lpn.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyeGtobAu/iCQunfBtoef\nA9AuuDk8Kduo8pM3aB6b5i8b6HoL5S6Q116ekfpg6U1G+Kodm69+b5tAukAl3A5t\nx7+zzQFejL2b1KPqkZMWlqj4syFmRE66lOKed/mZZz5MqEymW08PAASwpWGFdH4m\ncNWWUU3Hu+fjTXkqxR2s9sm2vQ9ErItPUHiXZ+1nhCNPEIzvVzAfzky68Nw+YP94\nGbponzjhrd8t7YW2IhQuXrz9xaoHR4Gtw1aH7SQDBzCaeo5iaXMhDGJO6RIgWxIP\nGgsolevTRzkuJMRipJOQzK6wLWarIDtK+TTe7QH494Uuj1zJvR/WZAi2jMNPomXM\n7QIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8lpn2.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8sedOqOxQqv+4yK07arG\nWxt8j8IthE8G0YNN6Im9SB3MOWxiLmLCxxGRaQhcGq/W5j27Zr+MDLsBUY67eW5Q\n667We3GorKzgoQ8e32rhCtfo/P3eZP3ZhRaDEiFOUdN9qc9E8vhi2wLiMm1dAnzn\nqkWSnvTQey2jJm0paFeidGB4/3DVwhDlbCoe6b6g1Z9ABKqEAXI7WLJjSq3l+5qO\nAynScJLkqZ8/igzxlNIHJTHPmSqLOgD8+Abzbb5SUp/wj5jyYBRqOBKM1qEnOE8T\nBTH6faCDB88BcZ9zLl8imndhlLqUVze/Te0DN80BDh0lZ2GlNpm14L9W9QdANuzQ\nwQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/k8lpwee.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkRlJrTu2qgIUibttxPqv\n2unfjfDWk3aF7CjUrCCM3WV+RzjoF6lQKym57o3muIuXY+O84KExBrlWZvMe0zVM\n6wN0fYU21urzSwcwCc2xetolg5BOLS9U4y5gR10UGuoOWeB5Z8r0deobuE9+YMEi\nRKIVrN8bDwLb8C/qWtrCVPz/BZ7nGhALYggTTzkdm1vrgWMOVR+pdb4mf0mDbiX1\n3Fb273F2u7qOPqaIBX5JXAfPxMmsgguWjQEiEEN4C2fzYbRpzhwmL2dk+niey4+R\n4zFdzNdNX3GlwBQHhGtbmt5mKivgE87ncnZ6LgCURdxhJ0doMuLusBEJgZ6EOitk\n2wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/kf23f-mnt.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1msQhd8jun9HD6ZMJeLv\n530rCgotQZRgvHVUBOhN95yQbmnVWKqZp3AAxCgBjfBoL6qXvmeiJiioCdJCZOEA\nf9AUH2keJOkFhu4xj5xG39aVss17dWqBPEV32JT9H/GZtXSCSe6xgvzLbtVsOQl7\nlzksx52Y/Swe7yvdMMBTKTkcXry9RY6E5gHtVJblSG7QFLjSs3sndo9dfhLUaAys\nMxawIzoQjeZCOdJ5uKK5LkmB1mPEI0uvavCbqxLOitbccntyjOv8652iLjqD4/mx\nQXqnLR3IpYhl0Tnly1bHbYFmFBYUu4OLsdtR3tOa6U1frjG3RJrzu2C+CN2ulaX/\n5QIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/kf23f.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxHkWUXttsB/dAvjh0dLm\nBCd3h//QOmcBPvQUMirVHv6w0fnZ5irmUpCUaeJRkdSkc9xSunh5gYtE/M6CMne5\n58yv+bpnDo9tHfUxIonRaktA0pgFw2i7uHyHA0XH6B2IycmyRCRotL3KJaygHkqI\nn8ysHJ6rYVvmY1Yu8YGo4Chzv96dlULAgzMdmJcxFiMG1B140qp1QK/AIArFr893\nVqiShvJj6492/MpR/W7TYxz6AbRj/bOEh71MHqG+5fEVF6fn4+G37AaOUHL+oz8r\nMO+PVH1o2beibiPn+l5NC3i2TB7nF8KIvHrOCo05fnWpVfZO43ki3mO5MQDZCP1Y\ngwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/kf23fwee.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAse+KN3Tj1YZdkc9AUVx/\nmy7QekrbDY6xdcqifU1HRDJEYL7tfaJqofVtv9tiFn+NlcWpU/gSD9Q2dJFtsdN6\nBaZyeVT4rhEr09WqkPFh8wGs5dbhAPYcyDzjdP2uGQnFawWV7rc7xSTJFhVCNRk6\n4a8Hld/VC28QtCYFaR9mXvFygcSWZ0H9d/ofwg7AwwRNiRXAyFZ4UXYM7f+kOUmG\nJbwwu2Te+Rao4H7i0xb50XbkysdSDQBkjaHO0SBL6zMml1XTFC1oDEYPi8N3Wdca\nYk2DzJwfY6qdtNo9cOCEPgoWab7xMmu+XEi5W2bWHAF2BmHxAGK7bnY/OVAipyD9\nIwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/kid23q.pem",
    "content": "-----BEGIN PUBLIC KEY-----\r\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApaY5LP7/8EMb/72h7prT\r\nT6k8v5heHhvqAYANOOcEI6zz9Q7oKShZ8swcN65re22ctwpwYCB3DOwmRVqVr8Fx\r\n/nZbhyS1MqjvvbaJECR5qnP+DWo9en7RrJ0wsXqV2su4VwMwoY6Tyh4/uK5xYABr\r\nyYjsqa12gJXMwboBEbvdAPrualkan35+qfoakajFOgECy2Ps1UF93rebXJaOt1O1\r\n6R79V1isPiGdVIHrsoLawDyJRCBvDsCmb7B0fRzxVUxUldkbGmTDo5HlV67hEO6D\r\nT4DKHA6vQ46VRQUiqi7yYt+cuRVV0us0haOv279Mml1bKJCjtVjGKpxq8WaSzFFs\r\niQIDAQAB\r\n-----END PUBLIC KEY-----"
  },
  {
    "path": "keys/lg1152.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkNkhcArb1al1SWazlsT6lAdA7\noq1lqOkC0ullyDveuJJTjfordgGxYBpk6fxUhJgmIZJgFXIkGcrj9Iv/iy5EomR+\n2lBokhh822ssLN6NqW8V+D6DA948qdX4IW6/4jswbXotSWRBv3Emhkh7l6zl2XY3\nkKq2cQIffONSDjAANwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lg1154_netcast.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkh+pwyk0MCwTkjTQTc7+SKhao\nWZ8RjphJHJo/J911E23waJS3uBU7xfck5lgLHc0MwHYocYUJ74mjBCrJ1QRt5ppt\n/1qIswG0xyTallg7+5m4wASqAilOtzXM1d2Iqeru9808rzSBmtac2zQzbkq+J6LB\nWfh4w+gWUVDyVrILZwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lg1154_webos.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjyC+5bEEE25JvwZxASvbkoF1t\n/zs7jgkj2Vv2yoPMAdHan9PumHYo2IthEWjLdA6BfTskYSc9RPeDAKMIPmV6MzrU\nnQkkW4uxPXnV48gERtSnfQcGFHsQyJpeEBP3skcZC/38mpWnCDLFxeahJiG8zSmP\nwBc4bMW7Yv0a6vsAewIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lm14.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3CAuN+IdjzWOQIsL60Y7+I813\nn7Ra0U1EmumjtO0YeLAY1k1HLhdpCF0WY2UNa0E4SzAWOsOOhmHBASJMWlIDEl8p\neN9WXdInANwh0KhS6v4lyXTAhwH2BPy9JhoYrqAJpWhETIsgUYWHdWv2mdCN0PBZ\nitX+rRyeVFYOi+eFSQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lm15u.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOJne7d1AULNFGTe/soOcYhUsN\ntKXlglSCxV9eR/WsfdOtMCJtoewBtohYBS09M7RgP4eSgwgmHWagL7qx3NldIAAa\nVgR0zSRx1vHFAs2Mbbppzc7rGuxHMOpXP8lMo0hGy4VTpisAhLdyIfc7QJib+9VS\nujxGPrfiVbaplyNwjQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lm18a.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq9yS4v9QyOoX5NP4y9mQ\naAi6S4qoLTJon61p5PmyAS07xTU9ArYt5Rx/JjmVEAXoU9BAZAMU1n6hR3hxEovo\nlSy4JBlHAH+LbmvHON8XBFRPDtyrhjDRz3iaqM/7WpVEWtmoSaWlNfWdEb/9XChR\nCczLkZxvkeq+LlxKo/mG3mkzkBzEozq2Hx6ETmC9VsG9w7o1pU3Km0c2px1DcRby\nF1X3EEm2F6DYuwKk4E9jMtrvSAoXGQrZvffJtvccjffHBS2zHdu58YavQm4tpE/3\nLQwypd2ueZGCJp5NegODHXDKKclAwGJniUC/2rTX/5ErZ49iurdyJHHZ4F0Khf25\nAwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lm21a.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtXZUiPWMvvDIzZi8bZHA\nrmSNQnXVgcYVLJG5Y8EnFFPcu4Yi9MF/ftoLnMTEBhtdu3XTtbxew3GPP5nrIbcm\noqNwLMVXK9G4oJAhEeswgARWhLJwASE8WnJ+9MuxgZD2OZVp63P04/alolMZw+OM\npNyeYF2xDuD4dHtzZAsj3adUmk7lw+IT8zVv31t+npxW2Vd6w0FG9j+eRPKTJ0jO\ngR3wXqGFoLfe7HxBX64uZEETF+gIQFEOEJsm+QskE1r9On98YIDckUlQ3azlxToH\n0vrNDRWSj7jmgWZkVmBaLKNMxsAgwC/r+wgHI46I77qtqdy4JfgNLJJR05T2CaRo\nfwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lm21an.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvmH6LxtCAWEbiSWDwfAj\nG4AVATdk5lc2zmPQB6Qv4rQfZcwSKbh5H4R4mKKHD/MKKAbFDQMTfMtdPgO9k8+Q\n8y3UfyCk3lBF9SENeQlJ+I5tuIbMb0GAVCPES5e28DeVzdVAYZpUhidtq4HXa9QD\n/3bNnk0TpGy0TrUcvANJ4GniSxXiu30pH9D2vQHFZOiISWtRrHtEvUtWchmnnBKG\nnSiy6Tpin5mDcEwDw4d5mDB4tGBeA3QaQVGDGC2ypN0KlN//S6EVfcyhmQU+zWei\nZ0MOSU9RNn7w1ZYtNBAHWxXiSLp9+xAY2crOfChNisX+ywBsCCLjnSdf58//JmxD\nzQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lm21ann.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApFnPQdukfvMBBW2euXBw\nY2djHEecfMbc/GI8axwSFwldAo4M3+qbLCCP0W0qGvTAWOgpJZLqLCPoGI4SiS2b\nOzOK9Khy8xEoIVjM74FrUGQ8Vr30Zh3cmNWBn29VRgsjEhtjTlHTCIC/YfiGM7sT\nZhwI0NjLyLJiGZtiPkacJWH02Gma8nsvIZMEYZPYviJenjJo8/PkNGQxXmQM+Ih+\n+a+WGDQFmCUhMzbev/O61wybFpLG+NW4lIx6EtOxS2tRMrren6HqVRF4nW1wURWZ\nTq4lEpBqFUEURk99qZPW0GHKMXUPWYiICrHwqGMB3eeZ6tjo8uR9IANKFQJbhOzD\nzwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lm21u.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz49aVG3dPRd98oTlw5DN\nL8iGZacnoeRxkqjwAtlI9Bl7Rujf9R/o3B0gGQXCbdWQ62xsagxv/bOUCrYMtsaD\nufOo7+bsukPX2Mz2OJFUaPKA22wMW5m2ccs+ZkdBt0t4OSLzd6ROdEmRTLG7tnj4\n6AiAk8BTSiLrABE2GF5j+I7Q2fyg2hhHDWO3R8pC0lBMdSOG4hzNRxnzKcgmbo1j\nq0Ro1929tQ8VK49j6PY3iQUJQDvPNbzWdYAhDwfSp6sRE7ggRdR3gYPqRjyFVPYH\nxhakC4uowzT6JDlb3S29bgyxqdjrYjh+JgKLVOyxjlKR6b5U6LMaWKOXbB4tk9ci\nlwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/lm21ut.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3RrEqzeR8db8ZtpVGFl\nQSc48VYW/ckMHTStUhFOLz0G3h98nuNNhg+tfkUun9bZQAesENdkAerbs9DjaIi1\nlRM88Ng2WfUY64p0cfBxdGEsjs1wepJ88BKy8bic4yC20zWcIyCshWy+oXM2Yry5\ngCjJwTnntkrtOeO5QuThudvP2k2P1IzqgdRQ5gK2AuJAjeLmS8gs1p+lyDlBXqG5\nBpVksBmnHnCYrUktLuR1z/cZN1bAPupX3ZWu8OWC4i3BT0QWakfOhYbyBRaa6lCX\nCodnsnUPT8uOgPioRPznJKJa1+kFYHnTcy5YKBJLWyI6ylb85Sf+qtCAZPNp76ZU\nXwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/m14.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC94ihi++eWPZHV2x14kz8KvaWu\nsuSOQPLMUvH4mppctZIMDm65XX1XuWuVlpRtDlwvoDT1UEz/A8Y9DVy7fSABeDyM\nESvG5LxqDx56e3i3spsqQndx/+Y+dbu20B/8NNVdaN1CkW21oIkYYXt0QK2SLBF5\nE1UYwCQFL7vbK6kfkQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/m16.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8FNygls/BI8MQnLCczjr\nSjKWNyC3nuwrtmJYT51JzI2oq1Q/VHBCJlWD0pIYZKnFilWCCM68fxGGUj/n7ekU\n2TPZJQ33fcF4jeP2iNu/PmXkLXwA8K9017NTjNcj31a7Z9OcKmpJ/Up2XSAPkrKc\n9/edetzsmT5m0MsXo615Y+qleTbdUXmzE4A/8/hazNyan5jxjoBwCEhYdGQX1gXa\nwUJG4zyXo9sSfrR2JMlLX42F77EUYbG6XYO8FJlgreoLyw2TIBRIR4oKRTxv0ZVv\nnu6nh/1yPWE+AQL6nlkrZByDHpX1RxbzhvNp/bTbeBbzPMEazavFXvb8JrpBs7GS\nkwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/m16p.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsFK3Fw+If1BMF2epkKBY\n/RuSPBMD448ZDq5Sved31VPtYflCM4c57K0HQPhnSL+AvwYrfCZ7Lv7T7GDbILOQ\nOq2qWMmtqUMt0bBT90MbtxQRdvNs6KAoFwhE91+2JPtDfa0f8Tge51ZhYJqh4NbA\nhzkVgu6juVgSqXoKRZKy/YMO+ZmTAyqEWcqiczKpT84O/pGk2j33PXb4VE7UVslQ\nlYsk5akNdnLLGBA2H41qi/rDcCshggN/R9USeRgrTp2zr1c27RV9BIRPeCfN1jLf\nXtGvgcPbDcn8FWdbFrWLjhkHZYvT+cZ9ur7zKiB/i57MkQL2xtYyyTuqnH+082Tf\n4wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/m16p3.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz7WrBwmE+jel2wBUeFtb\noV93IbGcwoRVfGA6j0G5rN/oCGVseC5g2pkGm/U6gukaLVO6FC2Sp6jfnqG0LfB1\nHY8Ezf7dQOVlgoMjPGtbGJKnW6SvhsukcCQViXwO33wm0biPcrPtH2mDYx5E3kJi\n3+QhhKC+Em+Jb+ajSnAkMPhwCZpBvuvqqf4clorLbGWz2QdoOaS7z7FsmWS7GCN7\nHKF0qFq0SSUsu/Plv2vxuJ3+R95qG2swVGSY/OXfzMK0JVdjU5onpzzXPfOKwTep\nOB+8fbTqsgERNfthSJP0psciKDmzXbtP/yjg51Sb4nWn2x97HaMjvsc/I1l2ysjh\n3wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/m16pp.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnP+kj6qXfiiSMa/mN/dC\nP/vasilwyu0DLKrOkJb+X00IY9LSS5O4g4wcTrG6RUJLZ0+r1y+mRWFS0zMIatlh\n3NEe29u7SlhMFzvgPwjC29qWrxI1HfcXXrIV8VLeAW21sM0IaVLEVALmGy3itYIc\nXRO1o6RBYAQ/ABwbJha8ClEdDXcXWiDyqg9ZIBN3qmZ/aZxa4n3h5Ggf92/kRCKI\nFZFfe/1HzcfglOQAH0FRJlbzrPyj4ymVmM04V3wu0Ibgdl8wJXWenZHIsS5Y/n18\nqR7dfOKwHjsRFGmLYqxk5U6Ks2WrMLzG6vnKji+oAcjf99fcPh950GMhMWQq67E7\nHwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/m23.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5cBUq+bAeiSsj45B4cvi\noHxeKj1aU7VUrP+f/ll8TQg5dOG7F1J+o6E6tkH7WCfoImwnuKjIeEjIjVZQv0KP\nVCPIEJpQWYs2n0+bqQTDdt1LHbDzej5vu4AS5phW4c0XCl20THPlXysyppk3eKMJ\nNPjuIxeLHhmEOulv10JN94WEI33saLI7GNsWRuyRnvXaFKeVaDSrSvHM/rHtzWuq\n5t+Te+rhglPBqjoD2swMuQIFtIvK6M/3TpUwAA0afTpwDc1kyI0NZDgH99AV7oaR\njLGP46hwxU1f7MbW+enUG3g65bbvs9vMM4uHL7MwFrQTD6Ar7tganhBfcxuBdtHI\n7wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/m2_sspm.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEpUSxzbMqpwvKLn2FKTyQHuUY\nh5f/qydAwKOXPwN9IPVyxH3OiiyI5mxuw5lSEt+dgnkczbOLF54Xz4qBW4Dt8iD2\ntO1rsKDVykEozdmLjxPmf3wDalM63IwNGe+QgosC7sB7xjtTAGq/DrWEOIh1nO1s\n/4079RA853cwga3YJQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/m3.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz4Vi5HM4NsE09eCLCQXX\n8DNGWA/XFF2Fycs0Ki4aih2drl/GWu6W9AAaS8wafyNkJ2PpF7Krs5NwtqbwrayD\nzHRUiVx878ZcZVek6NbByjgXA9WXXjw55LeHpqr4wtyrBR7s4HPa5QdlyvKHx9EY\ngT5/9WGm261pBYkifnT1yLStqBs778WWLCJm828bIIs4jd2EystiTazP1Bk6Fa4E\nNJxjSkwmAUjuxTiyR7Q/pYnMjOdr09GyJRXQ4LagtdjX4uVMkObPFc98s5nHBxzP\nTfN/1IBQHdZFDTY4VRDXkT9UNMwxCHRF+ayCumf1zp/STcoTwVyleVacsg8Li++6\nmQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/mtk5369.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL0sBwpPjjT9yYZPpXej4/TW7f\nERA/rCDHPtZwb3YBFy40g45XAvjukh9VUFY84uOA2cX7OaQKfoeM8WhtRQdqNEf3\nQ0QyY/dQZiRqnnYQKYk8GALC3V9/CgXIfNy+yHP3VCBXuTluA9SpXBTGdFxJCQpa\neJkeze3moUCZPnuQqQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/mtk5398.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDyVpYMXOhXKj4pkSv6ROs6kaQp\nTjCKzR71mf3Upw1YmrXhFT+nNCtjqo/JenuupxW1lCyovCMZFOVDdG+Y+OyM5oCc\n0mgVJs6fyHAGz2FIUwULy3NU27/f4M0cmX/qCjOSEt4WPvHwtCIuT6KiWZ6X2qCp\nPbzFkkzNc1PF5yq2CQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/netflix_pub.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6Qu5GAw/ITjDcuHnSTZP56fRT\njtdCZj2SDdDtMP7MOJ2GoCRA8kRkhj0sFtMwwCHiydEiv+A3bshJwGxI0lYYeZi8\nd7LhELZZSALecT0pimbXc9EFMc7DCCSAIJfR5lXNeut+JIBU6fwLq/bTc22mUtfW\niwc6Rx3nxN45HMMhUwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o18.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/HyMayJG0kzUA9XKbxi\nrE4vOqVZKtlVJj8bzQAUtoxxguQDz0T1t1HmbtDKLfhSlcwNM/rpilA5nIepArGe\nczNzYFTYYBV9HsSI1VuSrEfCILGtq0RbIMHCnvkt2RCwn1QWNS24k5dr0tI7kVmD\nb6DKmLNmmKUGsG5EdVvkTw4jB6g4bOk8Ji6LFq6MY7gS+90f3BdxDavKukEoQ8HI\n6xNpZAHrCe+KDAOnLbkrILBzpXpJLD2aujJSYwDCr8vxNCVizENM8H0B1NLxDlef\nfvgh3P5ch6uVKFw2hwcZC3TRkfur1i1na4tyRCjPqS3Fg0p0kZrfjMUkLkFywT0k\n/QIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o18_2019.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2cLO2n6G4YkXuxOvGNoG\nh32B3Zl7a6fJEg1rOb6yjo1YsfQ2jijkpjlBeZKnsZGPodyzKmm21o7XArlwbn2c\nvFFk8kf7UjyuPR1a1SghsiuAnxJjGD31TcEgD/uBtWPyqrKSu8cu0FnyC63ZmfuZ\nLBgvgvnupqH1RbiQEOPoUnbwTryTFKyNtpt6MCwsRxExQxxLgcn+aHLoVs5jqkyu\nqSrMtI4ol5Udu9mmQ5VMdkOVjAXue1xvCEW4ld2NnNTDkmIlmXrqJrPjxQ2l+rRe\nW7cyzmV6ZZZYXCG4YWPdefW+EzjzOJzemG5dSeH2jUPfBb4cx2qYx2ToZS5Blnaz\nfwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o18k.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv4VvbWUx/5imL7lUyBJK\nABGPNAPjVT4w3BRCwVOAkITtMk2VM3fWirZrH2UE40NL/wzdjqVCC0+PTHXvDeGj\n3LLcyhaESNz2Pn2qavWgKP1YWA5ctqphrSrPQGZ3CBc/Iu+lMYJLnzx6LL2BGezn\nhe4oxrkA6tOoiERgNnCGisnHZs5vHDZhU5lYAXQk3kYWzKG7+z5DOl/OA0C/wkDh\n0gUGQ7OxDcQiCdi1SUyTkHoFgJK4fBXC62LTfaZzAI2yGDoMtz6JcipxX/WZKBwX\n9XCaImnS020vWl4ikfGcq376gOAN+wUCwACyLPnfpdkmfFm+Cqfc2tmhKkz+bwaX\n8wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o20.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwbLByTYxeXUTG/+8nndC\nfoFPXU75yEi2LXTKrpa6vIO6AKFaE/0cvJz4ZJ6gEomf6LiQvjne9f+GLZgmzHs3\nndwl7JUdp5/TNnx8l1iITY8gAN4Gc46APT8RaR4hLTxY25r2MnxxM8S20U4g09Ql\n8fjaZcYh8GXZDrmBTtpMfzDRsoKIF1wGyvWvLRYD097VEwgKjmP+HUUyxL3Pmnf1\nH2R9o7wSzVJhRTui0eABklFT5SWH+GiaxjM7eEpO7vztJ0l9fxReNR9xnYjJV/YO\nCWWLidBvFjSXgmpH+NPJS8g5XvvQHxgLf6UJiLMTM+BtN8YQNWTvn38GPGQCvOcw\nLQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o208k.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn2T8zysvjAQgAAelDcZ0\nB1ONDwzFYmSCS67vT1/mzOi8xuiV1uht0bY8o+ku9z54zHMZZ4DL3KpbcVRW06J3\nX7htGX/FBnEA/Qrj9QRyxjq2rVhjgxwoToa9PPIySLXuSLF7RV5imB/dKld1RVNq\nf5R0RJL4OSMZ84usTVbN5Mdi1zghevMw76ZsHHIQqnXCBA49/VZdp3TGXqaw6pYS\nHYwrDYGTR3H+ICci4ZiqyVh/g81JL8GGtButyWGWw+ykffN1dUycH0rmu/DQ3F0M\n6ZbMswnmRtEGq2fI7MlfOvsMIgSdC9Soq3hQul4uISCKi+4+DNY+VjMbI8I/oSkZ\nzQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o20n.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt+9X5Iu6Z9fxu5egIpsb\n5yWadtIk8aYNggd5EFBJoiO/oD0zjLIc6aoAV01tJp3t93ngq3BS6hAIE+vSkGJI\nCwImAIMRtot0wmS5aPQB+4ImgChgZeEpU/86oWBtiap2eN6WEaRtKiA1InfLF4Ai\n8qiQX1PXr9X4Z2UJDbOi0nJU1adVOm9v98O4k0m/Qtirw1YRDOD0xLlVXalgaaCS\n640NsipAggowKm1esiCTupYmwSklvJtqLTR7LYy/9w4J8ePo0ZQscsVvVjlTnY4O\nV87/1dFOqzVRoP2TuCp501F/8YjkHVOuLb9P2uS+CZZzGkPLIowFtyCJ6HD43+rt\ndQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o22.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs+tQtULZxECErZGR9mfy\nf9ieRBkISQ7gOTCKcV6VD0e4ifnAjUR3YLDoZcMyaNfIuUlu7cd18mK6YvKDP9yn\n1LhoUrby8EoqWAM7EltSW0K4TdSIUbn1HDT0WIb+lE1flLTlyuCfE2LWjjh6Y5gN\nJiIRiaI27CZLK+kbBfab2IUXtEJJpsNKwaQ7Is3ZkBJyoOFZu489nL1YDU/nwrVC\n6rUgT0P+15S6ONuc63IY3TLqFPi/7TS3cwaYCoBjutVU2hGv+WdMx9IMVLGzHFMx\nPGulCb2uRQILBzONhibC+wCwVkC5ARqeK433fmG62tapOhMxTPrq9EjIrZPCsjFZ\n3wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o22n.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwDunPi+oDUiwolB2kMZB\nIKHAHdd0zGMT+RrbqsQFKozRfdZjDtiTCFBj2Rugjnw62VBSffnLqBRDdRksYCqw\ni91wXkJb/FZ8CbKfndFkTOR4eMhUgS9p2iw7lRz4lwe50LI9ANcPJfWCLmwhxa4s\nW28Rc2tVOxyMbSS76HCnoql5hdMNoLsImtguS+ytGho0AHyIRGQejSv/scR1h1g5\nxt0VL5hsKIsbTaAjnvqTYCalj55P9PkVcMJWLmac827ViwDZB5l5hfX2bNN1j41V\nYkHIUBCBikP+k/+/16kPD8Ow9ZPWb7ulrxmvXLewu5hy8A8kIHYBG8X+59zMI8A7\nXwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o22n2.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhi0GGEK2o7GrmGsMXSz3\n3pJNJ2sUdp36IdqJBgxYuJMO2QPvg5Axh+8Qdi3g9qqL3vvyWpMXJtDcS9lHIaxh\nsm3MYFETsUBk6y7fPM72Ob/RdTARs+vG5S9j5B5z6dGgoVPUTwnBBhfsTgJLIdek\nyER/xjV7EQ9blA1gY3htWWf6KIvlY3lIF8xp+L0olNy3zdTLzkPdboVMhPCCnacZ\nW1U6U4Y34s7YSEMQp2+QMzHwwXNtrZapDZjq8wooGxPAryDAdFLILvjILXtvGD89\nQv0J5E8/wS3GngxBL6jVnaPjk2yLJMnBPxhKTsd+uBRJ7X6/JXM86LebNVj5wTu+\n5wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o22n28k.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7ktbTHcQcFld59Vn9dXy\nivgkaVKYG8vhRdQRUMvEjP8O+NgasOhZ3PNy0bJsqihxhprj6wfSxIZbdqGkXhLs\namWdykhOYWwAbs0rrh4yrHX2sa/IqZfxxEJlulCYaUu5gzi1tZ9/3ga2B4g4CVOO\nYcOmKtWCv/ZpRpSHaxNdevHK/PIYElMssuiksvqArMV6dwn05/B81U7kEMUFKvbP\nBl0OHahmGcQ+HFBRCnys0YIUYd/IOvj7LXTOZQBsqCBIWLdCtBYSPkT+1rQTHb5Q\neqA9BAJsKcbSqRu42g+j88lDJEa6rKuxTuqpJEabEhuyKgIMoK5mVzBdeLNu2qoU\n/QIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o22n3.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvEh5Njtd5dL7Bv0Bemo4\n8KL0/kPtJeVF5Alc6n2nC6mLpSdEcNdONTlFKbCl3CpeYg1G0GL+WosG9gowSPuG\nSeG0u1ZWXprWeqALiwvaL637AK4jtM10u2oR4v0lP4/wrBBuLHbHp1xvXenQOZIT\nBN8tbFQoEtuHIu6HlCDjC11g+emzvvkXhHBpD+TGpGaz3jmnNqYYeCyvUTNsmoVL\nPKrQuRY4rFSmxiZvE0rsYWTckR4nNwrh4WJ1sNOmcJ910jmgcE4/EXJv2f5QVIYR\nX2zP76NTzlANclqzjfshISk73gxx9ZY3vLQKYShp9P3lH50ip9yGumML3I5lhjKj\nwQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o24.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3Tg2oafPMSxlLX8uPIXh\n1rsn8Zx5GNvahJjxKYBftrgS96c8k9n717vRtE9bTssXRVjf7b3rKIOQ3odRMtpq\nwZIkml4ZSg2p/M8YNhHLN4oNxBS7CN26SajiZbwu9HabFHWYoS54LiUkrFQKh9fD\nKFGDY0PYY8BdjKBWyoljj9ZckqjQffaDJMtakJMIhfG7cLI+HcNNyPovUcA0AQU8\nGBaFNvzMWiYEMuJMQu/C9kjWimRrAIXyH8AvP1gkc+yb6fdxO2K5Joo3/CrRfL1R\nvBs5F/QZCRX82WMNzhgtBycreAPxb5R62pfgf21QGeiz4uFsX8u0pKBNpOFMVUvQ\nWQIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "keys/o24n.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApPw4IzWaja49cPlyZl15\n7XAsJIETa1RhuN+gxih8iNZy2/hk8mGSWNc9w41K0lDvb+4TSP+1teUjEeFUZ9Rc\nlxe22PHki7nLArG1vO0jV4+2S5YJFdcspIJuCJG4E48VIk77x8tgzeseZY+maip+\nftCHCKYr70JWQsxRBblzsrbWuyKnbx5nfyVpzLdEBBZPKoS7CO5a8bkW1DGN0t4n\n+FZqbWuZqGsLRTls98/WkcD/mU7jwN1fQCidM0RJozlCGKqkFz9sMaQgBu30VAyr\nA2MTa/IlCVVDrTT3ZKkd58J2mTkgcUapQUpDB1927wPK1Hm+1NchIw5CxtW5/o6q\nSwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "partinfo.py",
    "content": "#!/usr/bin/env python2\nimport os, struct, sys, binascii, datetime, fnmatch\ndef allzero(string):\n        for x in string:\n                if ord(x):\n                        return False\n        return True\n\ndef allFF(string):\n        for x in string:\n\t\tif ord(x) != 0xFF:\n\t\t\treturn False\n\treturn True\n\ndef validate(date_text):\n\ttry:\n\t\tdatetime.datetime.strptime(date_text, '%Y-%m-%d')\n\texcept ValueError:\n\t\t#raise ValueError(\"Invalid Partition Table File\")\n\t\tsys.exit(\"Invalid Partition Table File\")\n\ndef fancyprint(str, pad):\n\tastr = \"|\"\n\tfor c in range(pad):\n\t\tastr+=\" \"\n\tastr+=str\n\tfor c in range(pad):\n\t\tastr+=\" \"\n\tastr+= \"|\"\n\n\tfor c in range(len(astr)):\n\t\tsys.stdout.write('-')\n\tprint \"\"\n\tprint astr\n\tfor c in range(len(astr)):\n\t\tsys.stdout.write('-')\n\tprint \"\"\n\n\nif not len(sys.argv) == 2:\n\tprint \"Usage: %s part.pak\" % sys.argv[0]\n\tsys.exit()\n\nif not os.path.exists(sys.argv[1]):\n\tsys.exit(\"Invalid file specified\")\n\nwith open(sys.argv[1], \"rb\") as partpak:\n\t#partinfo struct, used by:\n\t#\tmtk2013\n\t#\tlg1154\n\tpartmap_struct = \"<4s4s4sB3x\"\n\tdevice_struct = \"<32sQQ4s4siI\"\n\tpart_struct = \"<32sQQ32sIIBBI2x\"\n\t(magic, cur_epk_ver, old_epk_ver, npartition) = struct.unpack(partmap_struct, partpak.read(struct.calcsize(partmap_struct)))\n\t(devname, devsize, devphys, devvirt, devcached, devbandwith, devused) = struct.unpack(device_struct, partpak.read(struct.calcsize(device_struct)))\n\tdevname = devname.replace(\"\\x00\",\"\") #remove empty chars from string\n\n\tismtk1 = fnmatch.fnmatchcase(devname, \"mtk3569-emmc\") #match mtk2012\n\tismtkm1 = fnmatch.fnmatchcase(devname, \"mtk5369-emmc\") #match mtk2012\n\tismtk2 = fnmatch.fnmatchcase(devname, \"mtk3598-emmc\") #match mtk2013\n\tismtkm2 = fnmatch.fnmatchcase(devname, \"mtk5398-emmc\") #match mtk2013\n\tis1152 = fnmatch.fnmatchcase(devname, \"l9_emmc\") #match 1152\n\tis1154 = fnmatch.fnmatchcase(devname, \"h13_emmc\") #match 1154\n\tisbcm1\t= fnmatch.fnmatchcase(devname, \"bcm35xx_map0\") #match broadcom\n\tisbcm2\t= fnmatch.fnmatchcase(devname, \"bcm35230_map0\") #match broadcom\n\tismstar= fnmatch.fnmatchcase(devname, \"mstar_map0\") #match mstar\n\tif ismtk1 or ismtkm1:\n\t\tmodel=\"Mtk 2012 - MTK5369\"\n\telif ismtk2 or ismtkm2:\n\t\tmodel=\"Mtk 2013 - MTK5398\"\n\telif is1152:\n\t\tmodel=\"LG1152\"\n\telif is1154:\n\t\tmodel=\"LG1154\"\n\telif isbcm1:\n\t\tmodel=\"BCM 2011 - BCM35230\"\n\telif isbcm2:\n\t\tmodel=\"BCM 2010 - BCM35XX\"\n\telif ismstar:\n\t\tmodel=\"Mstar Saturn/LM1\"\n\telse:\n\t\tmodel=\"Unknown\"\n\n\tif ismtk2 == False and is1154 == False:\n\t#alternative structs\n\t\tif ismtk1 == True or is1152 == True:\n\t\t\t#mixed struct, used by\n\t\t\t#\tmtk2012:\n\t\t\t#\tlg1152\n\t\t\t#\n\t\t\t#\tpartinfo header\n\t\t\t#\tmtdinfo device struct\n\t\t\t#\tMixed mtdinfo AND partinfo struct\n\t\t\t#\t\t32sII32s --> old mtdinfo part\n\t\t\t#\t\tsIIBBI2x --> new partinfo part\n\t\t\tpartpak.seek(0)\n\t\t\tpartmap_struct = \"<4s4s4sB3x\"\n\t\t\tdevice_struct = \"<32sII4s4siI\"\n\t\t\tpart_struct = \"<32sII32sIIBBI2x\"\n\t\t\t(magic, cur_epk_ver, old_epk_ver, npartition) = struct.unpack(partmap_struct, partpak.read(struct.calcsize(partmap_struct)))\n\t\t\t(devname, devsize, devphys, devvirt, devcached, devbandwith, devused) = struct.unpack(device_struct, partpak.read(struct.calcsize(device_struct)))\n\t\telse:\n\t\t\t#mtdinfo struct, used by:\n\t\t\t#\tbcm\n\t\t\t#\tlm1\n\t\t\t#\tmstar\n\t\t\tpartpak.seek(0)\n\t\t\tpartmap_struct = \"<4s4s4sBB2x\"\n\t\t\tdevice_struct = \"<32sII4s4siI\"\n\t\t\tpart_struct = \"<32sII32sIIBBBx\"\n\t\t\t(magic, cur_epk_ver, old_epk_ver, nmap, npartition) = struct.unpack(partmap_struct, partpak.read(struct.calcsize(partmap_struct)))\n\t\t\t(devname, devsize, devphys, devvirt, devcached, devbandwith, devused) = struct.unpack(device_struct, partpak.read(struct.calcsize(device_struct)))\n\t\t\t#mtdinfo struct supports 4 mtd devices, but LG uses only one nand/device\n\t\t\t#seek ahead the 3 empty slots\n\t\t\tpartpak.read(struct.calcsize(device_struct)*3)\n\n\tdevname = devname.replace(\"\\x00\",\"\") #remove empty chars from string\n\tdevsize = float(devsize)\n\tif devsize%(1024*1024*1024) == 0:\n                #Gigabytes\n\t\tdevsize = devsize/1024/1024/1024\n\t\tdevsizeunit = \"GB\"\n\telse:\n\t\t#Small MTD, use Megabytes\n\t\tdevsize = devsize/1024/1024\n\t\tdevsizeunit = \"MB\"\n\n\n\t#swap magic byte array\n\tmagic = list(magic)[::-1]\n\n\t#if epk fields are not empty, swap them\n\tif not allzero(cur_epk_ver) and not allzero(old_epk_ver):\n\t\tcur_epk_ver = list(cur_epk_ver)[::-1]\n\t\told_epk_ver = list(old_epk_ver)[::-1]\n\t\tepk_ver = 1\n\telse:\n\t\t#empty apk fields, don't display\n\t\tepk_ver = 0\n\n\t#encode magic and epk data (if present) to hex\n\tfor e in range(4):\n\t\tmagic[e] = magic[e].encode(\"hex\")\n\t\tif epk_ver == 1:\n\t\t\tcur_epk_ver[e] = cur_epk_ver[e].encode(\"hex\")\n\t\t\told_epk_ver[e] = old_epk_ver[e].encode(\"hex\")\n\n\t#join epk data with dot (.)\n\tcur_epk_ver = '.'.join([str(x) for x in cur_epk_ver])\n\told_epk_ver = '.'.join([str(x) for x in old_epk_ver])\n\n\t#build magic string\n\tmagic = magic[0]+magic[1]+\"-\"+magic[2]+\"-\"+magic[3]\n\t#check if it's a valid date\n\tvalidate(magic)\n\n\tfancyprint(\"Detected: \"+model, 10)\n\n\tprint \"Partition Table Info:\"\n\tprint \"-------------------------------\"\n\n\tprint \"Date Magic: %s\" %magic\n\tif not epk_ver == 0:\n\t\tprint \"Epk version: %s\" % cur_epk_ver\n\t\tprint \"Old Epk version: %s\" % old_epk_ver\n\tif not npartition == 1 and not npartition == 0:\n\t\tprint \"Partition Count: %d\" % npartition\n\n\tprint \"MTD Name: %s, size %d %s\" % (devname, devsize, devsizeunit)\n\tprint \"Partition Table:\"\n\tprint \"-------------------------------\"\n\n\tfor part in range(npartition):\n\t\t(partname, partoff, partsize, partfn, partfs, partsw, partIsUsed, partIsValid, partflags) = struct.unpack(part_struct, partpak.read(struct.calcsize(part_struct)))\n\t\tpartname = partname.strip()\n\t\tfancyprint(\"Partition \"+str(part), 5)\n                print \"Name: \\t\\t\\t %s\"%partname\n                if partsize%(1024*1024) == 0:\n                        partsize = partsize/1024/1024\n                        partsizeunit = \"MB\"\n                elif partsize%1024 == 0:\n                        partsize = partsize/1024\n                        partsizeunit = \"KB\"\n                else:\n                        partsizeunit = \"bytes\"\n                print \"Partition Size: \\t %d %s\"%(partsize, partsizeunit)\n                print \"Filename: \\t\\t %s\"%partfn\n                partfs = float(partfs)\n                if partfs%(1024*1024) == 0:\n                        partfs = partfs/1024/1024\n                        fsunit = \"MB\"\n                elif partfs%1024 == 0:\n                        partfs = partfs/1024\n                        fsunit = \"KB\"\n                else:\n                        fsunit = \"bytes\"\n                print \"Filename Size: \\t\\t %d %s\"%(partfs, fsunit)\n                partsw=\"%08x\"%partsw\n                partsw=\".\".join([\"\".join(partsw[i:i+2]) for i in xrange(0, len(partsw), 2)])\n                partflags = '{0:08b}'.format(partflags)\n                partflags=int(partflags)\n                isFixed = bool(partflags & 1)\n                isMaster = bool(partflags & 2)\n                isKey = bool(partflags & 4)\n                isCache = bool(partflags & 8)\n                isData = bool(partflags & 16)\n                isSecure = bool(partflags & 32)\n                isErase = bool(partflags & 64)\n                partflags = list()\n                if isFixed:\n                        partflags.append(\"FIXED\")\n                if isMaster:\n                        partflags.append(\"MASTER\")\n                if isKey:\n                        partflags.append(\"IDKEY\")\n                if isCache:\n                        partflags.append(\"CACHE\")\n                if isData:\n                        partflags.append(\"DATA\")\n                if isSecure:\n                        partflags.append(\"SECURED\")\n                if isErase:\n                        partflags.append(\"ERASE\")\n                print \"File Version: \\t\\t %s\"%partsw\n                print \"Partition in use: \\t %s\"%bool(partIsUsed)\n                print \"Partition Flags: \\t %s\" %\",\".join(partflags)\n"
  },
  {
    "path": "sonar-project.properties",
    "content": "## THIS FILE IS AUTOGENERATED\n## edit .sonarcloud_gen.sh instead\nsonar.projectKey=openlgtv_epk2extract\nsonar.organization=openlgtv\n\nsonar.issue.ignore.multicriteria=r1\n\n# format string is not a string literal\nsonar.issue.ignore.multicriteria.r1.ruleKey=c:S5281\nsonar.issue.ignore.multicriteria.r1.resourceKey=**\n\nsonar.inclusions=src/*.c,src/lzhs/*.c,src/stream/*.c,src/tools/*.c,include/*.h,include/lzhs/*.h,include/realtek/*.h,include/stream/*.h\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "set(INC ${CMAKE_SOURCE_DIR}/include)\n\nadd_definitions(-D_GNU_SOURCE)\n\nif(APPLE)\n\tinclude_directories(SYSTEM ${INC}/osx)\nendif()\n\nadd_library(mfile mfile.c)\nadd_library(utils util.c util_crypto.c thpool.c)\n\ntarget_include_directories(mfile PUBLIC ${INC})\ntarget_include_directories(utils PUBLIC\n\t${INC}\n\t${INC}/u-boot\n\t${OPENSSL_INCLUDE_DIR}\n)\n\ntarget_link_libraries(utils ${OPENSSL_LIBRARIES} mfile)\n\nadd_subdirectory(cramfs)\nadd_subdirectory(squashfs)\nadd_subdirectory(lz4)\nadd_subdirectory(lzma)\nadd_subdirectory(jffs2)\nadd_subdirectory(lzhs)\nadd_subdirectory(stream)\nadd_subdirectory(tools)\n\nadd_executable(epk2extract\n\tmain.c crc32.c\n\tepk.c epk1.c epk2.c epk3.c\n\tmediatek_pkg.c\n\tmediatek.c philips.c symfile.c partinfo.c minigzip.c lzo-lg.c\n\trealtek.c\n)\n\ntarget_compile_definitions(epk2extract PRIVATE\n\t-DUSE_MMAP #for gzip\n)\n\ntarget_compile_options(epk2extract PRIVATE\n\t-Wunused\n)\n\ntarget_link_libraries(epk2extract\n\tmfile utils cramfs squashfs\n\tlz4 jffs2 lzhs stream\n\t${ZLIB_LIBRARIES} ${LZO_LIBRARIES}\n\t${CMAKE_THREAD_LIBS_INIT} ${M_LIB}\n)\n"
  },
  {
    "path": "src/cramfs/CMakeLists.txt",
    "content": "add_library(cramfs cramfsswap.c uncramfs.c)\ntarget_include_directories(cramfs PUBLIC\n\t${INC}\n\t${INC}/cramfs\n)"
  },
  {
    "path": "src/cramfs/cramfsswap.c",
    "content": "/*\n    cramfsswap - swaps endian of a cramfs file\n\n    last modified on 2006-11-08 by kju\n\n    Copyright (c) 2004-2006 by Michael Holzt, kju -at- fqdn.org\n    To be distributed under the terms of the GPL2 license.\n\n*/\n\n#include <stdio.h>\n#include <inttypes.h>\n#include <sys/stat.h>\n#include <cramfs/cramfs_fs.h>\n#include <os_byteswap.h>\n#include <zlib.h>\t\t\t\t/* for crc32 */\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define BUFFERSIZE\t16384\n#define MAXFILES\t4096\n#define BLKSIZE\t\t4096\t\t/* Should this be a command line option? */\n\nint cramswap(char *sinfile, char *soutfile) {\n\tuint32_t superblock_in[16], superblock_out[16], flags, blockpointer_in, blockpointer_out, blockpointer_last, crc, *mapping;\n\tuint16_t endiantest;\n\tuint8_t inode_in[12], inode_out[12];\n\tstruct cramfs_inode inode;\n\tunsigned int filecnt, file, filepos, remaining, nblocks, copybytes, readbytes, x;\n\tunsigned int *fileoffset, *filesize;\n\tunsigned char buffer[BUFFERSIZE], is_hostorder, host_is_le, file_is_le;\n\tint infile, outfile;\n\tint size;\n\n\t/*if ( argc != 3 )\n\t   {\n\t   fprintf(stderr, \"Usage: %s <in> <out>\\n\", argv[0]);\n\t   exit(1);\n\t   } */\n\n\tif ((infile = open(sinfile, O_RDONLY)) < 0) {\n\t\tperror(\"while trying to open binary input file\");\n\t\treturn -1;\n\t}\n\tif ((outfile = open(soutfile, O_RDWR | O_TRUNC | O_CREAT, 0644)) < 0) {\n\t\tperror(\"while trying to open image output file\");\n\t\texit(1);\n\t}\n\n\tif (read(infile, &superblock_in, sizeof(superblock_in)) != sizeof(superblock_in)) {\n\t\tperror(\"while trying to read superblock\");\n\t\texit(1);\n\t}\n\n\t/* Detect endianness of host */\n\tendiantest = 1;\n\tif (((uint8_t *) & endiantest)[0] == 1)\n\t\thost_is_le = 1;\n\telse\n\t\thost_is_le = 0;\n\n\t/* Detect endianness of file */\n\tif (superblock_in[0] == CRAMFS_MAGIC) {\n\t\tis_hostorder = 1;\n\t\tfile_is_le = host_is_le;\n\t} else if (superblock_in[0] == bswap_32(CRAMFS_MAGIC)) {\n\t\tis_hostorder = 0;\n\t\tfile_is_le = !(host_is_le);\n\t} else {\n\t\tfprintf(stderr, \"cramfs magic not detected\\n\");\n\t\texit(1);\n\t}\n\n\tif (file_is_le)\n\t\t//printf(\"Filesystem is little endian, will be converted to big endian.\\n\");\n\t\treturn -1;\n\telse\n\t\tprintf(\"Filesystem is big endian, will be converted to little endian.\\n\");\n\n\t/* Swap Superblock */\n\tsuperblock_out[0] = bswap_32(superblock_in[0]);\t/* Magic */\n\tsuperblock_out[1] = bswap_32(superblock_in[1]);\t/* Size */\n\tsuperblock_out[2] = bswap_32(superblock_in[2]);\t/* Flags */\n\tsuperblock_out[3] = bswap_32(superblock_in[3]);\t/* Future Use */\n\tsuperblock_out[4] = superblock_in[4];\t/* Sig 1/4 */\n\tsuperblock_out[5] = superblock_in[5];\t/* Sig 2/4 */\n\tsuperblock_out[6] = superblock_in[6];\t/* Sig 3/4 */\n\tsuperblock_out[7] = superblock_in[7];\t/* Sig 4/4 */\n\tsuperblock_out[8] = bswap_32(superblock_in[8]);\t/* fsid crc */\n\tsuperblock_out[9] = bswap_32(superblock_in[9]);\t/* fsid edition */\n\tsuperblock_out[10] = bswap_32(superblock_in[10]);\t/* fsid blocks */\n\tsuperblock_out[11] = bswap_32(superblock_in[11]);\t/* fsid files */\n\tsuperblock_out[12] = superblock_in[12];\t/* Name 1/4 */\n\tsuperblock_out[13] = superblock_in[13];\t/* Name 2/4 */\n\tsuperblock_out[14] = superblock_in[14];\t/* Name 3/4 */\n\tsuperblock_out[15] = superblock_in[15];\t/* Name 4/4 */\n\twrite(outfile, &superblock_out, sizeof(superblock_out));\n\n\t/* Check Flags */\n\tif (is_hostorder)\n\t\tflags = superblock_in[2];\n\telse\n\t\tflags = superblock_out[2];\n\n\t/* I'm not sure about the changes between v1 and v2. So for now\n\t   don't support v1. */\n\tif ((flags & 0x1) == 0) {\n\t\tfprintf(stderr, \"Error: Not cramfs version 2!\\n\");\n\t\texit(1);\n\t}\n\n\t/* This should be done later */\n\tif (flags & 0x100) {\n\t\tfprintf(stderr, \"Error: Filesystem contains holes (not supported yet)\\n\");\n\t\texit(1);\n\t}\n\n\t/* Do we really need this? */\n\tif (flags & 0x400) {\n\t\tfprintf(stderr, \"Error: Filesystem has shifted root fs flag (not supported)\\n\");\n\t\texit(1);\n\t}\n\n\t/* Something else? */\n\tif (flags & 0xFFFFFFFC) {\n\t\tfprintf(stderr, \"Error: Filesystem has unknown/unsupported flag set!\\n\");\n\t\texit(1);\n\t}\n\n\t/* Get Filecounter (which is number of file entries plus 1 (for the root inode) */\n\tif (is_hostorder)\n\t\tfilecnt = superblock_in[11];\n\telse\n\t\tfilecnt = superblock_out[11];\n\tprintf(\"Filesystem contains %d files.\\n\", filecnt - 1);\n\n\tfileoffset = (unsigned int *)malloc(filecnt * sizeof(*fileoffset));\n\tif (fileoffset == NULL) {\n\t\tperror(\"fileoffset malloc error\");\n\t\texit(1);\n\t}\n\n\tfilesize = (unsigned int *)malloc(filecnt * sizeof(*filesize));\n\tif (filesize == NULL) {\n\t\tfree(fileoffset);\n\t\tfileoffset = NULL;\n\t\tperror(\"filesize malloc error\");\n\t\texit(1);\n\t}\n\n\t/* Set filepos (in words) */\n\tfilepos = 16;\n\n\t/* Initialise the counter for the \"real\" (stored) files */\n\tremaining = 0;\n\n\t/* Read directory entries (first one is the root inode) */\n\tfor (file = 0; file < filecnt; file++) {\n\t\t/* Read and swap file inode */\n\t\tif (read(infile, &inode_in, sizeof(inode_in)) != sizeof(inode_in)) {\n\t\t\tperror(\"while trying to read directory entry\");\n\t\t\texit(1);\n\t\t}\n\n\t\t/* Swap the inode. */\n\n\t\tinode_out[0] = inode_in[1];\t/* 16 bit: mode */\n\t\tinode_out[1] = inode_in[0];\n\n\t\tinode_out[2] = inode_in[3];\t/* 16 bit: uid */\n\t\tinode_out[3] = inode_in[2];\n\n\t\tinode_out[4] = inode_in[6];\t/* 24 bit: size */\n\t\tinode_out[5] = inode_in[5];\n\t\tinode_out[6] = inode_in[4];\n\n\t\tinode_out[7] = inode_in[7];\t/* 8 bit: gid width */\n\n\t\t/* Stop the madness! Outlaw C bitfields! They are unportable and nasty!\n\t\t   See yourself what a mess this is: */\n\n\t\tif (file_is_le) {\n\t\t\tinode_out[8] = ((inode_in[8] & 0x3F) << 2) | ((inode_in[11] & 0xC0) >> 6);\n\n\t\t\tinode_out[9] = ((inode_in[11] & 0x3F) << 2) | ((inode_in[10] & 0xC0) >> 6);\n\n\t\t\tinode_out[10] = ((inode_in[10] & 0x3F) << 2) | ((inode_in[9] & 0xC0) >> 6);\n\n\t\t\tinode_out[11] = ((inode_in[9] & 0x3F) << 2) | ((inode_in[8] & 0xC0) >> 6);\n\t\t} else {\n\t\t\tinode_out[8] = ((inode_in[8] & 0xFD) >> 2) | ((inode_in[11] & 0x03) << 6);\n\n\t\t\tinode_out[9] = ((inode_in[11] & 0xFD) >> 2) | ((inode_in[10] & 0x03) << 6);\n\n\t\t\tinode_out[10] = ((inode_in[10] & 0xFD) >> 2) | ((inode_in[9] & 0x03) << 6);\n\n\t\t\tinode_out[11] = ((inode_in[9] & 0xFD) >> 2) | ((inode_in[8] & 0x03) << 6);\n\t\t}\n\n\t\tif (is_hostorder) {\n\t\t\t/* copy the input for our use */\n\t\t\tmemcpy(&inode, &inode_in, sizeof(inode_in));\n\t\t} else {\n\t\t\t/* copy the output for our use */\n\t\t\tmemcpy(&inode, &inode_out, sizeof(inode_in));\n\t\t}\n\n\t\t/* write the converted inode */\n\t\twrite(outfile, &inode_out, sizeof(inode_out));\n\n\t\t/* Copy filename */\n\t\tif (read(infile, &buffer, inode.namelen << 2) != inode.namelen << 2) {\n\t\t\tperror(\"while trying to read filename\");\n\t\t\texit(1);\n\t\t}\n\t\twrite(outfile, &buffer, inode.namelen << 2);\n\n\t\t/* Store the file size and file offset */\n\t\tfilesize[file] = inode.size;\n\t\tfileoffset[file] = inode.offset;\n\n\t\t/* filepos is increased by namelen words + 3 words for the inode */\n\t\tfilepos += inode.namelen + 3;\n\n\t\t/* Has this entry a data chunk? */\n\t\tif ((S_ISREG(inode.mode) || S_ISLNK(inode.mode)) && inode.size > 0) {\n\t\t\tremaining++;\n\t\t}\n\n\t}\n\n\t// Here we deal with LE XIP image stuffed into BE cramfs image.\n\t// We just convert superblock and inodes endianess while leaving the content of the rest as is...\n\tif (superblock_out[10] == 0) {\n\t\tdo {\n\t\t\treadbytes = read(infile, &buffer, BUFFERSIZE);\n\t\t\twrite(outfile, &buffer, readbytes);\n\t\t} while (readbytes > 0);\n\n\t\tclose(infile);\n\t\tclose(outfile);\n\t\treturn 0;\n\t}\n\n\t/* Now process the individual files data. Because cramfs will share the compressed\n\t   data for two identical input files, we do this by starting at the begin of the\n\t   data, identifiying the accompanying file, process the file data, and move to\n\t   the next until no file is left                                                */\n\twhile (remaining) {\n\t\t/* Find the file */\n\t\tfor (file = 1; file < filecnt && fileoffset[file] != filepos; file++) ;\n\t\tif (fileoffset[file] != filepos) {\n\t\t\t/* Not found */\n\t\t\tfprintf(stderr, \"Did not find the file which starts at word %x, aborting...\\n\", filepos);\n\t\t\texit(1);\n\t\t}\n\n\t\t/* Reduce file counter for each file which starts here (as said, can be more\n\t\t   than one if the cramfs had identical input files) */\n\t\tfor (x = 1; x < filecnt; x++)\n\t\t\tif (fileoffset[x] == filepos)\n\t\t\t\tremaining--;\n\n\t\t/* Number of blocks of this file */\n\t\tnblocks = (filesize[file] - 1) / BLKSIZE + 1;\n\n\t\t/* Swap the blockpointer */\n\t\tfor (x = 0; x < nblocks; x++) {\n\t\t\tif (read(infile, &blockpointer_in, 4) != 4) {\n\t\t\t\tperror(\"while trying to read blockpointer\");\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tblockpointer_out = bswap_32(blockpointer_in);\n\t\t\twrite(outfile, &blockpointer_out, 4);\n\n\t\t\tfilepos++;\n\t\t}\n\n\t\t/* Last blockpointer points to the byte after the end\n\t\t   of the file */\n\t\tif (is_hostorder)\n\t\t\tblockpointer_last = blockpointer_in;\n\t\telse\n\t\t\tblockpointer_last = blockpointer_out;\n\n\t\t/* Align to a word boundary */\n\t\tblockpointer_last += (4 - (blockpointer_last % 4)) % 4;\n\n\t\t/* Copy the file data */\n\t\tcopybytes = blockpointer_last - (filepos << 2);\n\t\twhile (copybytes > 0) {\n\t\t\treadbytes = (copybytes > BUFFERSIZE) ? BUFFERSIZE : copybytes;\n\n\t\t\tif (read(infile, &buffer, readbytes) != readbytes) {\n\t\t\t\tperror(\"while trying to read file data\");\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\twrite(outfile, &buffer, readbytes);\n\n\t\t\tcopybytes -= readbytes;\n\t\t}\n\n\t\t/* Set new filepos */\n\t\tfilepos = (blockpointer_last) >> 2;\n\t}\n\n\t/* Copy the remaining data (padding) */\n\tdo {\n\t\treadbytes = read(infile, &buffer, BUFFERSIZE);\n\t\twrite(outfile, &buffer, readbytes);\n\t} while (readbytes > 0);\n\n\t/* recalculate the crc */\n\tsize = lseek(outfile, 0, SEEK_CUR);\t/* should not fail */\n\tmapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, outfile, 0);\n\tif (mapping != MAP_FAILED) {\n\t\tcrc = crc32(0L, Z_NULL, 0);\n\t\tmapping[8] = is_hostorder ? bswap_32(crc) : crc;\n\t\tcrc = crc32(crc, (unsigned char *)mapping, size);\n\t\tprintf(\"CRC: 0x%08x\\n\", crc);\n\t\tmapping[8] = is_hostorder ? bswap_32(crc) : crc;\n\t\tmunmap(mapping, size);\n\t} else {\n\t\tperror(\"mapping failed\");\n\t}\n\n\t/* Done! */\n\tclose(infile);\n\tclose(outfile);\n\n\treturn 0;\n}\n"
  },
  {
    "path": "src/cramfs/uncramfs.c",
    "content": "//\n// Uncramfs\n// A program to unpack a cramfs image\n//\n// Copyright Andrew Stitcher, 2001\n//\n// Licensed according to the GNU GPL v2\n//\n\n// C things\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n\n// Unix things\n#include <unistd.h>\n#include <errno.h>\n//#include <dirent.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <sys/mman.h>\n#include <sys/fcntl.h>\n#ifndef __APPLE__\n#    include <sys/sysmacros.h>\n#endif\n\n// Application libraries\n#include <zlib.h>\n\n// Cramfs definitions\n#include \"cramfs.h\"\n\n#include \"os_byteswap.h\"\n\n#define PAGE_CACHE_SIZE (4096)\n\n/* The kernel assumes PAGE_CACHE_SIZE as block size. */\nstatic unsigned long blksize = PAGE_CACHE_SIZE;\n\nstatic char *opt_devfile = NULL;\nstatic char *opt_idsfile = NULL;\n\nstatic int DIR_GID = 0;\n\nvoid do_file_entry(const u8 * base, const char *dir, const char *path, const char *name, int namelen, const struct cramfs_inode *inode);\n\nvoid do_dir_entry(const u8 * base, const char *dir, const char *path, const char *name, int namelen, const struct cramfs_inode *inode);\n\n///////////////////////////////////////////////////////////////////////////////\n\nu32 compressed_size(const u8 * base, const u8 * data, u32 size) {\n\tconst u32 *buffs = (const u32 *)(data);\n\tint nblocks = (size - 1) / blksize + 1;\n\tconst u8 *buffend = base + *(buffs + nblocks - 1);\n\n\tif (size == 0)\n\t\treturn 0;\n\telse\n\t\treturn buffend - data;\n}\n\nvoid uncompress_data(const u8 * base, const u8 * data, u32 size, u8 * dstdata) {\n\tconst u32 *buffs = (const u32 *)(data);\n\tint nblocks = (size - 1) / blksize + 1;\n\tconst u8 *buff = (const u8 *)(buffs + nblocks);\n\tconst u8 *nbuff;\n\tint block = 0;\n\tuLongf len = size;\n\n\tif (size == 0) {\n\t\treturn;\n\t}\n\n\tfor (; block < nblocks; ++block, buff = nbuff, dstdata += blksize, len -= blksize) {\n\t\tuLongf tran = (len < blksize) ? len : blksize;\n\t\tnbuff = base + *(buffs + block);\n\t\tif (uncompress(dstdata, &tran, buff, nbuff - buff) != Z_OK) {\n\t\t\tfprintf(stderr, \"Uncompression failed\");\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\nint stats_totalsize;\nint stats_totalcsize;\nint stats_count;\nint stats_compresses;\nint stats_expands;\n\nvoid clearstats() {\n\tstats_totalsize = 0;\n\tstats_totalcsize = 0;\n\tstats_count = 0;\n\tstats_compresses = 0;\n\tstats_expands = 0;\n}\n\nvoid updatestats(int size, int csize) {\n\t++stats_count;\n\tstats_totalsize += size;\n\tstats_totalcsize += csize;\n\n\tif (size >= csize) {\n\t\tstats_compresses++;\n\t} else {\n\t\tstats_expands++;\n\t}\n}\n\nvoid printstats() {\n\tprintf(\"\\n[Summary:]\\n\");\n\tprintf(\"[Total uncompressed size:    %9d]\\n\", stats_totalsize);\n\tprintf(\"[Total compressed size:      %9d]\\n\", stats_totalcsize);\n\tprintf(\"[Number of entries:          %9d]\\n\", stats_count);\n\tprintf(\"[Number of files compressed: %9d]\\n\", stats_compresses);\n\tprintf(\"[Number of files expanded:   %9d]\\n\", stats_expands);\n\tprintf(\"\\n\");\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\nvoid printmode(const struct cramfs_inode *inode) {\n\tu16 mode = inode->mode;\n\n\t// Deal with file type bitsetc\n\tif (S_ISDIR(mode))\n\t\tprintf(\"d\");\n\telse if (S_ISLNK(mode))\n\t\tprintf(\"l\");\n\telse if (S_ISBLK(mode))\n\t\tprintf(\"b\");\n\telse if (S_ISCHR(mode))\n\t\tprintf(\"c\");\n\telse if (S_ISFIFO(mode))\n\t\tprintf(\"p\");\n\telse if (S_ISSOCK(mode))\n\t\tprintf(\"s\");\n\telse\n\t\tprintf(\"-\");\n\n\t// Deal with mode bits\n\tif (mode & S_IRUSR)\n\t\tprintf(\"r\");\n\telse\n\t\tprintf(\"-\");\n\tif (mode & S_IWUSR)\n\t\tprintf(\"w\");\n\telse\n\t\tprintf(\"-\");\n\tif (mode & S_IXUSR)\n\t\tif (mode & S_ISUID)\n\t\t\tprintf(\"s\");\n\t\telse\n\t\t\tprintf(\"x\");\n\telse if (mode & S_ISUID)\n\t\tprintf(\"S\");\n\telse\n\t\tprintf(\"-\");\n\tif (mode & S_IRGRP)\n\t\tprintf(\"r\");\n\telse\n\t\tprintf(\"-\");\n\tif (mode & S_IWGRP)\n\t\tprintf(\"w\");\n\telse\n\t\tprintf(\"-\");\n\tif (mode & S_IXGRP)\n\t\tif (mode & S_ISGID)\n\t\t\tprintf(\"s\");\n\t\telse\n\t\t\tprintf(\"x\");\n\telse if (mode & S_ISGID)\n\t\tprintf(\"S\");\n\telse\n\t\tprintf(\"-\");\n\tif (mode & S_IROTH)\n\t\tprintf(\"r\");\n\telse\n\t\tprintf(\"-\");\n\tif (mode & S_IWOTH)\n\t\tprintf(\"w\");\n\telse\n\t\tprintf(\"-\");\n\tif (mode & S_IXOTH)\n\t\tif (mode & S_ISVTX)\n\t\t\tprintf(\"t\");\n\t\telse\n\t\t\tprintf(\"x\");\n\telse if (mode & S_ISVTX)\n\t\tprintf(\"T\");\n\telse\n\t\tprintf(\"-\");\n}\n\nvoid printuidgid(const struct cramfs_inode *inode) {\n\tchar res[14];\n\n\tsnprintf(res, 14, \"%d/%d\", inode->uid, inode->gid);\n\tprintf(\" %-14s\", res);\n\n}\n\nvoid printsize(int size, int csize) {\n\tchar s[17];\n\n\t// As a side effect update the size stats\n\tupdatestats(size, csize);\n\n\tsnprintf(s, 17, \"%7d(%d)\", size, csize);\n\tprintf(\"%-16s \", s);\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\nvoid do_file(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode) {\n\tint fd;\n\tu8 *file_data;\n\tconst u8 *srcdata;\n\n\t// Allow for uncompressed XIP executable\n\tif (mode & S_ISVTX) {\n\t\t// It seems that the offset may not necessarily be page\n\t\t// aligned. This is silly because mkcramfs wastes\n\t\t// the alignment space, whereas it might be used if it wasn't\n\t\t// bogusly in our file extent.\n\t\t//\n\t\t// blksize must be a power of 2 for the following to work, but it seems\n\t\t// quite likely.\n\n\t\tsrcdata = (const u8 *)(((long)(base + offset) + blksize - 1) & ~(blksize - 1));\n\n\t\t//printsize(size, srcdata + size - (base + offset));\n\t\t//printf(\"%s\", name);\n\t} else {\n\t\t//printsize(size, compressed_size(base, base + offset, size));\n\t\t//printf(\"%s\", name);\n\t}\n\n\t// Check if we are actually unpacking\n\tif (path[0] == '-') {\n\t\treturn;\n\t}\n\t// Make local copy\n\tfd = open(path, O_CREAT | O_TRUNC | O_RDWR, mode);\n\tif (fd == -1) {\n\t\tperror(\"create\");\n\t\treturn;\n\t};\n\n\tif (ftruncate(fd, size) == -1) {\n\t\tperror(\"ftruncate\");\n\t\tclose(fd);\n\t\treturn;\n\t}\n\n\tfile_data = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n\tif (file_data == MAP_FAILED) {\n\t\tperror(\"mmap\");\n\t\tclose(fd);\n\t\treturn;\n\t}\n\t// Allow for uncompressed XIP executable\n\tif (mode & S_ISVTX) {\n\t\tmemcpy(file_data, srcdata, size);\n\t} else {\n\t\tuncompress_data(base, base + offset, size, file_data);\n\t}\n\n\tmunmap(file_data, size);\n\tclose(fd);\n\n}\n\nvoid do_directory(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode) {\n\t//printsize(size, size);\n\t//printf(\"%s\", name);\n\n\t// Check if we are actually unpacking\n\tif (path[0] == '-') {\n\t\treturn;\n\t}\n\t// Make the local directory\n\tif (mkdir(path, mode) == -1) {\n\t\tperror(path);\n\t\treturn;\n\t}\n}\n\nvoid do_symlink(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode) {\n\t// Allocate the uncompressed string\n\tu8 link_contents[size + 1];\n\n\t// do uncompression\n\tuncompress_data(base, base + offset, size, link_contents);\n\tlink_contents[size] = 0;\n\n\tprintsize(size, compressed_size(base, base + offset, size));\n\tprintf(\"%s -> %s\", name, link_contents);\n\n\t// Check if we are actually unpacking\n\tif (path[0] == '-') {\n\t\treturn;\n\t}\n\t// Make local copy\n\tif (symlink((const char *)link_contents, path) == -1) {\n\t\tperror(path);\n\t\texit(1);\n\t}\n}\n\nvoid do_chrdev(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode, int uid, int gid) {\n\t{\n\t\tchar s[17];\n\t\tsnprintf(s, 17, \"%3d, %3d\", major(size), minor(size));\n\t\tprintf(\"%-16s %s\", s, name);\n\t}\n\n\t// Check if we are actually unpacking\n\tif (path[0] == '-') {\n\t\treturn;\n\t}\n\t// Make local copy\n\tif (geteuid() == 0) {\n\t\tif (mknod(path, S_IFCHR | mode, size) == -1)\n\t\t\tperror(path);\n\t} else if (opt_devfile) {\n\t\tchar dfp[1024];\n\t\tchar *p;\n\t\tFILE *f;\n\n\t\tstrcpy(dfp, path);\n\t\tp = strrchr(dfp, '/');\n\t\tif (!p) {\n\t\t\tfprintf(stderr, \"Could not find path in '%s'\\n\", path);\n\t\t\treturn;\n\t\t}\n\t\tstrcpy(p + 1, opt_devfile);\n\t\tf = fopen(dfp, \"at\");\n\t\tif (!f) {\n\t\t\tperror(dfp);\n\t\t\treturn;\n\t\t}\n\t\tfprintf(f, \"%s,%08x,%u,%u,%08x\\n\", name, mode, uid, gid, size);\n\t\tfclose(f);\n\t}\n}\n\nvoid do_blkdev(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode, int uid, int gid) {\n\t{\n\t\tchar s[17];\n\t\tsnprintf(s, 17, \"%3d, %3d\", major(size), minor(size));\n\t\t//printf(\"%-16s %s\", s, name);\n\t}\n\n\t// Check if we are actually unpacking\n\tif (path[0] == '-') {\n\t\treturn;\n\t}\n\t// Make local copy\n\tif (geteuid() == 0) {\n\t\tif (mknod(path, S_IFBLK | mode, size) == -1)\n\t\t\tperror(path);\n\t} else if (opt_devfile) {\n\t\tchar dfp[1024];\n\t\tchar *p;\n\t\tFILE *f;\n\n\t\tstrcpy(dfp, path);\n\t\tp = strrchr(dfp, '/');\n\t\tif (!p) {\n\t\t\tfprintf(stderr, \"Could not find path in '%s'\\n\", path);\n\t\t\treturn;\n\t\t}\n\t\tstrcpy(p + 1, opt_devfile);\n\t\tf = fopen(dfp, \"at\");\n\t\tif (!f) {\n\t\t\tperror(dfp);\n\t\t\treturn;\n\t\t}\n\t\tfprintf(f, \"%s,%08x,%u,%u,%08x\\n\", name, mode, uid, gid, size);\n\t\tfclose(f);\n\t}\n}\n\nvoid do_fifo(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode, int gid, int uid) {\n\tprintf(\"                 %s\", name);\n\n\t// Check if we are actually unpacking\n\tif (path[0] == '-') {\n\t\treturn;\n\t}\n\t// Make local copy\n\tif (geteuid() == 0) {\n\t\tif (mknod(path, S_IFIFO | mode, 0) == -1)\n\t\t\tperror(path);\n\t} else if (opt_devfile) {\n\t\tchar dfp[1024];\n\t\tchar *p;\n\t\tFILE *f;\n\n\t\tstrcpy(dfp, path);\n\t\tp = strrchr(dfp, '/');\n\t\tif (!p) {\n\t\t\tfprintf(stderr, \"Could not find path in '%s'\\n\", path);\n\t\t\treturn;\n\t\t}\n\t\tstrcpy(p + 1, opt_devfile);\n\t\tf = fopen(dfp, \"at\");\n\t\tif (!f) {\n\t\t\tperror(dfp);\n\t\t\treturn;\n\t\t}\n\t\tfprintf(f, \"%s,%08x,%u,%u,%08x\\n\", name, mode, uid, gid, size);\n\t\tfclose(f);\n\t}\n}\n\nvoid do_socket(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode) {\n\tprintf(\"<UNIMPLEMENTED>  %s\", name);\n\n\t// Check if we are actually unpacking\n\tif (path[0] == '-') {\n\t\treturn;\n\t}\n}\n\nvoid do_unknown(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode) {\n\tprintf(\"<UNKNOWN TYPE>   %s\", name);\n}\n\nvoid process_directory(const u8 * base, const char *dir, u32 offset, u32 size, const char *path) {\n\tstruct cramfs_inode *de;\n\tchar *name;\n\tint namelen;\n\tu32 current = offset;\n\tu32 dirend = offset + size;\n\n\t// Do files\n\twhile (current < dirend) {\n\t\tu32 nextoffset;\n\n\t\tde = (struct cramfs_inode *)(base + current);\n\t\tnamelen = de->namelen << 2;\n\t\tnextoffset = current + sizeof(struct cramfs_inode) + namelen;\n\n\t\tname = (char *)(de + 1);\n\n\t\twhile (1) {\n\t\t\tassert(namelen != 0);\n\n\t\t\tif (name[namelen - 1])\n\t\t\t\tbreak;\n\t\t\tnamelen--;\n\t\t}\n\n\t\tdo_file_entry(base, dir, path, name, namelen, de);\n\n\t\tcurrent = nextoffset;\n\t}\n\n\t// Recurse into directories\n\tcurrent = offset;\n\twhile (current < dirend) {\n\t\tu32 nextoffset;\n\n\t\tde = (struct cramfs_inode *)(base + current);\n\t\tnamelen = de->namelen << 2;\n\t\tnextoffset = current + sizeof(struct cramfs_inode) + namelen;\n\n\t\tname = (char *)(de + 1);\n\n\t\twhile (1) {\n\t\t\tassert(namelen != 0);\n\n\t\t\tif (name[namelen - 1])\n\t\t\t\tbreak;\n\t\t\tnamelen--;\n\t\t}\n\n\t\tdo_dir_entry(base, dir, path, name, namelen, de);\n\n\t\tcurrent = nextoffset;\n\t}\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\nvoid do_file_entry(const u8 * base, const char *dir, const char *path, const char *name, int namelen, const struct cramfs_inode *inode) {\n\tint dirlen = strlen(dir);\n\tint pathlen = strlen(path);\n\tchar pname[dirlen + pathlen + namelen + 3];\n\tconst char *basename;\n\tu32 gid = inode->gid;\n\n\tif (dirlen) {\n\t\tstrncpy(pname, dir, dirlen);\n\t}\n\n\tif (pathlen) {\n\t\tif (dirlen) {\n\t\t\tpname[dirlen] = '/';\n\t\t\t++dirlen;\n\t\t}\n\t\tstrncpy(pname + dirlen, path, pathlen);\n\t}\n\n\tif (namelen) {\n\t\tif (pathlen + dirlen) {\n\t\t\tpname[dirlen + pathlen] = '/';\n\t\t\t++pathlen;\n\t\t}\n\t\tstrncpy(pname + dirlen + pathlen, name, namelen);\n\t}\n\n\tpname[pathlen + dirlen + namelen] = 0;\n\tbasename = namelen ? pname + dirlen + pathlen : \"/\";\n\n\t// Create things here\n\t//printmode(inode);\n\t//printuidgid(inode);\n\n\tif (S_ISREG(inode->mode)) {\n\n\t\tu32 size = inode->size;\n\n\t\tif (gid > DIR_GID) {\n\t\t\t// sirius: this is a special LG encoding of the size.\n\t\t\t// misusing gid field to encode the most significant byte of the size\n\t\t\tint lg = gid - DIR_GID;\n\t\t\tgid -= lg;\n\t\t\tlg = lg * 0x1000000;\n\t\t\tsize += (lg);\n\t\t}\n\n\t\tdo_file(base, inode->offset << 2, size, pname, basename, inode->mode);\n\t} else if (S_ISDIR(inode->mode)) {\n\t\tif (DIR_GID == 0) {\n\t\t\tDIR_GID = gid;\n\t\t}\n\t\tdo_directory(base, inode->offset << 2, inode->size, pname, basename, inode->mode);\n\t} else if (S_ISLNK(inode->mode)) {\n\t\tdo_symlink(base, inode->offset << 2, inode->size, pname, basename, inode->mode);\n\t} else if (S_ISFIFO(inode->mode)) {\n\t\tdo_fifo(base, inode->offset << 2, inode->size, pname, basename, inode->mode, inode->uid, inode->gid);\n\t} else if (S_ISSOCK(inode->mode)) {\n\t\tdo_socket(base, inode->offset << 2, inode->size, pname, basename, inode->mode);\n\t} else if (S_ISCHR(inode->mode)) {\n\t\tdo_chrdev(base, inode->offset << 2, inode->size, pname, basename, inode->mode, inode->uid, inode->gid);\n\t} else if (S_ISBLK(inode->mode)) {\n\t\tdo_blkdev(base, inode->offset << 2, inode->size, pname, basename, inode->mode, inode->uid, inode->gid);\n\t} else {\n\t\tdo_unknown(base, inode->offset << 2, inode->size, pname, basename, inode->mode);\n\t}\n\n\tif (geteuid() == 0) {\n\t\tif (lchown(pname, inode->uid, gid) == -1)\n\t\t\tperror(\"cannot change owner or group\");\n\t} else if (opt_idsfile && path && path[0]) {\n\t\tchar dfp[1024];\n\t\tchar *p;\n\t\tFILE *f;\n\n\t\tstrcpy(dfp, pname);\n\t\tp = strrchr(dfp, '/');\n\t\tif (!p) {\n\t\t\tfprintf(stderr, \"could not find path in '%s'\\n\", pname);\n\t\t\treturn;\n\t\t}\n\t\tstrcpy(p + 1, opt_idsfile);\n\t\tf = fopen(dfp, \"at\");\n\t\tif (!f) {\n\t\t\tperror(dfp);\n\t\t\treturn;\n\t\t}\n\t\tfprintf(f, \"%s,%u,%u,%08x\\n\", basename, inode->uid, inode->gid, inode->mode);\n\t\tfclose(f);\n\t}\n\n\tif (geteuid() == 0 || !opt_idsfile) {\n\t\tif (inode->mode & (S_ISGID | S_ISUID | S_ISVTX)) {\n\t\t\tif (0 != chmod(pname, inode->mode)) {\n\t\t\t\tperror(\"chmod\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\t//printf(\"\\n\");\n}\n\nvoid do_dir_entry(const u8 * base, const char *dir, const char *path, const char *name, int namelen, const struct cramfs_inode *inode) {\n\tint pathlen = strlen(path);\n\tchar pname[pathlen + namelen + 2];\n\n\tif (pathlen) {\n\t\tstrncpy(pname, path, pathlen);\n\t}\n\n\tif (namelen) {\n\t\tif (pathlen) {\n\t\t\tpname[pathlen] = '/';\n\t\t\t++pathlen;\n\t\t}\n\t\tstrncpy(pname + pathlen, name, namelen);\n\t}\n\n\tpname[pathlen + namelen] = 0;\n\n\t// Only process directories here\n\tif (S_ISDIR(inode->mode)) {\n\t\t//printf(\"\\n/%s:\\n\", pname);\n\t\tprocess_directory(base, dir, inode->offset << 2, inode->size, pname);\n\t}\n}\n\n///////////////////////////////////////////////////////////////////////////////\nint is_cramfs_image(char const *imagefile, char *endian) {\n\tstruct stat st;\n\tint fd, result;\n\tsize_t fslen_ub;\n\tint *rom_image;\n\tstruct cramfs_super const *sb;\n\n\t// Check the image file\n\tif (stat(imagefile, &st) == -1) {\n\t\tperror(imagefile);\n\t\texit(1);\n\t}\n\t// Map the cramfs image\n\tfd = open(imagefile, O_RDONLY);\n\tfslen_ub = st.st_size;\n\trom_image = mmap(0, fslen_ub, PROT_READ, MAP_SHARED, fd, 0);\n\tif (rom_image == MAP_FAILED) {\n\t\tperror(\"Mapping cramfs file\");\n\t\texit(1);\n\t}\n\n\tsb = (struct cramfs_super const *)(rom_image);\n\tint cram_magic = CRAMFS_MAGIC;\n\tif (!memcmp(endian, \"be\", 2))\n\t\tSWAP(cram_magic);\n\tresult = 0;\n\t// Check cramfs magic number and signature\n\tif (cram_magic == sb->magic || (memcmp(endian, \"be\", 2) && 0 == memcmp(sb->signature, CRAMFS_SIGNATURE, sizeof(sb->signature))))\n\t\tresult = 1;\n\n\tmunmap(rom_image, fslen_ub);\n\tclose(fd);\n\n\treturn result;\n}\n\nint uncramfs(char const *dirname, char const *imagefile) {\n\n\tstruct stat st;\n\tint fd;\n\tsize_t fslen_ub;\n\tu8 const *rom_image;\n\tstruct cramfs_super const *sb;\n\n\t// Check the directory\n\tif (access(dirname, W_OK) == -1) {\n\t\tif (errno != ENOENT) {\n\t\t\tperror(dirname);\n\t\t\texit(1);\n\t\t}\n\t}\n\t// Check the image file\n\tif (stat(imagefile, &st) == -1) {\n\t\tperror(imagefile);\n\t\texit(1);\n\t}\n\t// Map the cramfs image\n\tfd = open(imagefile, O_RDONLY);\n\tfslen_ub = st.st_size;\n\trom_image = mmap(0, fslen_ub, PROT_READ, MAP_SHARED, fd, 0);\n\tif (rom_image == MAP_FAILED) {\n\t\tperror(\"Mapping cramfs file\");\n\t\texit(1);\n\t}\n\n\tsb = (struct cramfs_super const *)(rom_image);\n\t// Check cramfs magic number and signature\n\tif (CRAMFS_MAGIC != sb->magic || 0 != memcmp(sb->signature, CRAMFS_SIGNATURE, sizeof(sb->signature))) {\n\t\tfprintf(stderr, \"The image file doesn't have cramfs signatures\\n\");\n\t\texit(1);\n\t}\n\t// Set umask to 0 to let the image modes shine through\n\tumask(0);\n\n\tclearstats();\n\n\t// Start doing...\n\tdo_file_entry(rom_image, dirname, \"\", \"\", 0, &sb->root);\n\tdo_dir_entry(rom_image, dirname, \"\", \"\", 0, &sb->root);\n\n\treturn 0;\n}\n"
  },
  {
    "path": "src/crc32.c",
    "content": "/* Crc - 32 BIT ANSI X3.66 CRC checksum files */\n\n#include <stdio.h>\n#include \"crc.h\"\n\n#ifdef __TURBOC__\n#    pragma warn -cln\n#endif\n\n/**********************************************************************\\\n|* Demonstration program to compute the 32-bit CRC used as the frame  *|\n|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71     *|\n|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level     *|\n|* protocol).  The 32-bit FCS was added via the Federal Register,     *|\n|* 1 June 1982, p.23798.  I presume but don't know for certain that   *|\n|* this polynomial is or will be included in CCITT V.41, which        *|\n|* defines the 16-bit CRC (often called CRC-CCITT) polynomial.  FIPS  *|\n|* PUB 78 says that the 32-bit FCS reduces otherwise undetected       *|\n|* errors by a factor of 10^-5 over 16-bit FCS.                       *|\n\\**********************************************************************/\n\n/* Need an unsigned type capable of holding 32 bits; */\n\ntypedef DWORD UNS_32_BITS;\n\n/* Copyright (C) 1986 Gary S. Brown.  You may use this program, or\n   code or tables extracted from it, as desired without restriction.*/\n\n/* First, the polynomial itself and its table of feedback terms.  The  */\n/* polynomial is                                                       */\n/* 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 */\n/* Note that we take it \"backwards\" and put the highest-order term in  */\n/* the lowest-order bit.  The X^32 term is \"implied\"; the LSB is the   */\n/* X^31 term, etc.  The X^0 term (usually shown as \"+1\") results in    */\n/* the MSB being 1.                                                    */\n\n/* Note that the usual hardware shift register implementation, which   */\n/* is what we're using (we're merely optimizing it by doing eight-bit  */\n/* chunks at a time) shifts bits into the lowest-order term.  In our   */\n/* implementation, that means shifting towards the right.  Why do we   */\n/* do it this way?  Because the calculated CRC must be transmitted in  */\n/* order from highest-order term to lowest-order term.  UARTs transmit */\n/* characters in order from LSB to MSB.  By storing the CRC this way,  */\n/* we hand it to the UART in the order low-byte to high-byte; the UART */\n/* sends each low-bit to hight-bit; and the result is transmission bit */\n/* by bit from highest- to lowest-order term without requiring any bit */\n/* shuffling on our part.  Reception works similarly.                  */\n\n/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */\n/*                                                                     */\n/*  1. The table can be generated at runtime if desired; code to do so */\n/*     is shown later.  It might not be obvious, but the feedback      */\n/*     terms simply represent the results of eight shift/xor opera-    */\n/*     tions for all combinations of data and CRC register values.     */\n/*                                                                     */\n/*  2. The CRC accumulation logic is the same for all CRC polynomials, */\n/*     be they sixteen or thirty-two bits wide.  You simply choose the */\n/*     appropriate table.  Alternatively, because the table can be     */\n/*     generated at runtime, you can start by generating the table for */\n/*     the polynomial in question and use exactly the same \"updcrc\",   */\n/*     if your application needn't simultaneously handle two CRC       */\n/*     polynomials.  (Note, however, that XMODEM is strange.)          */\n/*                                                                     */\n/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */\n/*     of course, 32-bit entries work OK if the high 16 bits are zero. */\n/*                                                                     */\n/*  4. The values must be right-shifted by eight bits by the \"updcrc\"  */\n/*     logic; the shift must be unsigned (bring in zeroes).  On some   */\n/*     hardware you could probably optimize the shift in assembler by  */\n/*     using byte-swap instructions.                                   */\n\nstatic UNS_32_BITS crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,\n\t0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,\n\t0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,\n\t0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n\t0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n\t0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,\n\t0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,\n\t0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n\t0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,\n\t0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n\t0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,\n\t0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n\t0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,\n\t0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\n\t0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n\t0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n\t0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,\n\t0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,\n\t0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,\n\t0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n\t0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,\n\t0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,\n\t0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,\n\t0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n\t0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,\n\t0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,\n\t0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,\n\t0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n\t0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,\n\t0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n\t0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,\n\t0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n\t0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,\n\t0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,\n\t0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n\t0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n\t0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,\n\t0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,\n\t0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,\n\t0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n\t0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,\n\t0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\n\t0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d\n};\n\nDWORD updateCRC32(unsigned char ch, DWORD crc) {\n\treturn UPDC32(ch, crc);\n}\n\nBoolean_T crc32file(char *name, DWORD * crc, long *charcnt) {\n\tFILE *fin;\n\tDWORD oldcrc32;\n\tint c;\n\n\toldcrc32 = 0xFFFFFFFF;\n\t*charcnt = 0;\n#ifdef MSDOS\n\tif ((fin = fopen(name, \"rb\")) == NULL)\n#else\n\tif ((fin = fopen(name, \"r\")) == NULL)\n#endif\n\t{\n\t\tperror(name);\n\t\treturn Error_;\n\t}\n\twhile ((c = getc(fin)) != EOF) {\n\t\t++*charcnt;\n\t\toldcrc32 = UPDC32(c, oldcrc32);\n\t}\n\n\tif (ferror(fin)) {\n\t\tperror(name);\n\t\t*charcnt = -1;\n\t}\n\tfclose(fin);\n\n\t*crc = oldcrc32 = ~oldcrc32;\n\n\treturn Success_;\n}\n\nDWORD crc32buf(char *buf, size_t len) {\n\tregister DWORD oldcrc32;\n\n\toldcrc32 = 0xFFFFFFFF;\n\n\tfor (; len; --len, ++buf) {\n\t\toldcrc32 = UPDC32(*buf, oldcrc32);\n\t}\n\n\treturn ~oldcrc32;\n\n}\n\n#ifdef TEST\n\nmain(int argc, char *argv[]) {\n\tDWORD crc;\n\tlong charcnt;\n\tregister errors = 0;\n\n\twhile (--argc > 0) {\n\t\terrors |= crc32file(*++argv, &crc, &charcnt);\n\t\tprintf(\"%08lX %7ld %s\\n\", crc, charcnt, *argv);\n\t}\n\treturn (errors != 0);\n}\n\n#endif /* TEST */\n"
  },
  {
    "path": "src/epk.c",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <string.h>\n#include <dirent.h>\n#include <ctype.h>\n\n#include <openssl/evp.h>\n#include <openssl/aes.h>\n#include <openssl/pem.h>\n#include <openssl/err.h>\n\n#include \"config.h\"\n#include \"epk.h\"\n#include \"epk2.h\"\n#include \"epk3.h\"\n#include \"util.h\"\n#include \"util_crypto.h\"\n\nstatic EVP_PKEY *_gpPubKey;\nstatic AES_KEY *aesKey;\nstatic int keyFound = 0;\nstatic int sigCheckAvailable = 0;\nstatic int firstAttempt = 1;\n\n/*\n * Checks if the given data is an EPK2 or EPK3 header\n */\nint compare_epak_header(uint8_t *header, size_t headerSize){\n\tif(compare_epk2_header(header, headerSize)){\n\t\treturn EPK_V2;\n\t} else if(compare_epk3_header(header, headerSize)){\n\t\treturn EPK_V3;\n\t} else if(compare_epk3_new_header(header, headerSize)){\n\t\treturn EPK_V3_NEW;\n\t}\n\n\treturn 0;\n}\n\n/*\n * Loads the specified Public Key for Signature verification\n */\nint SWU_CryptoInit_PEM(char *configuration_dir, char *pem_file) {\n\tOpenSSL_add_all_digests();\n\tERR_load_CRYPTO_strings();\n\tchar *pem_file_name;\n\tasprintf(&pem_file_name, \"%s/%s\", configuration_dir, pem_file);\n\tFILE *pubKeyFile = fopen(pem_file_name, \"r\");\n\tif (pubKeyFile == NULL) {\n\t\tprintf(\"Error: Can't open PEM file %s\\n\\n\", pem_file);\n\t\treturn 1;\n\t}\n\tEVP_PKEY *gpPubKey = PEM_read_PUBKEY(pubKeyFile, NULL, NULL, NULL);\n\t_gpPubKey = gpPubKey;\n\tif (_gpPubKey == NULL) {\n\t\tprintf(\"Error: Can't read PEM signature from file %s\\n\\n\", pem_file);\n\t\tfclose(pubKeyFile);\n\t\treturn 1;\n\t}\n\tfclose(pubKeyFile);\n\tERR_clear_error();\n\treturn 0;\n}\n\n/*\n * Verifies the signature of the given data against the loaded public key\n */\nint API_SWU_VerifyImage(void *signature, void* data, size_t imageSize, SIG_TYPE_T sigType) {\n\tsize_t hashSize;\n\tunsigned int sigSize;\n\tconst EVP_MD *algo;\n\n\tswitch(sigType) {\n\t\tcase SIG_SHA1:\n\t\t\thashSize = 0x40;\n\t\t\tsigSize = SIGNATURE_SIZE;\n\t\t\talgo = EVP_sha1();\n\t\t\tbreak;\n\t\tcase SIG_SHA256:\n\t\t\thashSize = 0x80;\n\t\t\tsigSize = SIGNATURE_SIZE_NEW;\n\t\t\talgo = EVP_sha256();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tprintf(\"Invalid sigType: %d\\n\", sigType);\n\t\t\treturn 0;\n\t}\n\n\tunsigned char md_value[hashSize];\n\tunsigned int md_len = 0;\n\tint result = 0;\n\n\tEVP_MD_CTX *ctx1, *ctx2;\n\tif ((ctx1 = EVP_MD_CTX_new()) == NULL)\n\t\treturn 0;\n\n\tif ((ctx2 = EVP_MD_CTX_new()) == NULL) {\n\t\tEVP_MD_CTX_free(ctx1);\n\t\treturn 0;\n\t}\n\n\tEVP_DigestInit(ctx1, algo);\n\tEVP_DigestUpdate(ctx1, data, imageSize);\n\tEVP_DigestFinal(ctx1, md_value, &md_len);\n\tEVP_DigestInit(ctx2, algo);\n\tEVP_DigestUpdate(ctx2, md_value, md_len);\n\n\tresult = EVP_VerifyFinal(ctx2, signature, sigSize, _gpPubKey);\n\n\tEVP_MD_CTX_free(ctx2);\n\tEVP_MD_CTX_free(ctx1);\n\n\treturn result;\n}\n\n/*\n * Wrapper for signature verification. Retries by decrementing size if it fails\n */\nint wrap_SWU_VerifyImage(\n\tvoid *signature, void* data,\n\tsize_t signedSize, size_t *effectiveSignedSize, SIG_TYPE_T sigType\n){\n\tsize_t curSize = signedSize;\n\tint verified;\n\t//int skipped = 0;\n\twhile (curSize > 0) {\n\t\tverified = API_SWU_VerifyImage(signature, data, curSize, sigType);\n\t\tif (verified) {\n\t\t\tif(effectiveSignedSize != NULL){\n\t\t\t\t*effectiveSignedSize = curSize;\n\t\t\t}\n\t\t\t//printf(\"Success!\\nDigital signature is OK. Signed bytes: %d\\n\", curSize);\n\t\t\t//printf(\"Subtracted: %d\\n\", skipped);\n\t\t\treturn 0;\n\t\t} else {\n\t\t\t//skipped++;\n\t\t}\n\t\tcurSize--;\n\t}\n\t//printf(\"Failed\\n\");\n\treturn -1;\n}\n\n/*\n * High level wrapper for signature verification\n */\nint wrap_verifyimage(void *signature, void *data, size_t signSize, char *config_dir, SIG_TYPE_T sigType){\n\tsize_t effectiveSignedSize;\n\tint result = -1;\n\tif(!sigCheckAvailable){\n\t\t// No key available, fail early\n\t\tif(!firstAttempt){\n\t\t\treturn -1;\n\t\t}\n\t\tfirstAttempt = 0;\n\t\tprintf(\"Verifying %zu bytes\\n\", signSize);\n\n\t\tDIR* dirFile = opendir(config_dir);\n\t\tif (dirFile == NULL){\n\t\t\tfprintf(stderr, \"Failed to open dir '%s'\\n\", config_dir);\n\t\t} else {\n\t\t\tstruct dirent* hFile;\n\t\t\twhile ((hFile = readdir(dirFile)) != NULL) {\n\t\t\t\tif (!strcmp(hFile->d_name, \".\") || !strcmp(hFile->d_name, \"..\") || hFile->d_name[0] == '.') continue;\n\t\t\t\tif (strstr(hFile->d_name, \".pem\") || strstr(hFile->d_name, \".PEM\")) {\n\t\t\t\t\tprintf(\"Trying RSA key: %s...\\n\", hFile->d_name);\n\t\t\t\t\tSWU_CryptoInit_PEM(config_dir, hFile->d_name);\n\t\t\t\t\tresult = wrap_SWU_VerifyImage(signature, data, signSize, &effectiveSignedSize, sigType);\n\t\t\t\t\tif(result > -1){\n\t\t\t\t\t\tsigCheckAvailable = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tclosedir(dirFile);\n\t\t}\n\t} else {\n\t\tresult = wrap_SWU_VerifyImage(signature, data, signSize, &effectiveSignedSize, sigType);\n\t}\n\n\tif (result < 0) {\n\t\tfprintf(stderr, \"WARNING: Cannot verify digital signature (maybe you don't have proper PEM file)\\n\\n\");\n\t} else {\n\t\tprintf(\"Succesfully verified 0x%x out of 0x%x bytes\\n\", effectiveSignedSize, signSize);\n\t}\n\treturn result;\n}\n\n/*\n * Decrypts the given data against the loaded AES key, with ECB mode\n */\nvoid decryptImage(void *srcaddr, size_t len, void *dstaddr) {\n\tunsigned int remaining = len;\n\tunsigned int decrypted = 0;\n\twhile (remaining >= AES_BLOCK_SIZE) {\n\t\tAES_decrypt(srcaddr, dstaddr, aesKey);\n\t\tsrcaddr += AES_BLOCK_SIZE;\n\t\tdstaddr += AES_BLOCK_SIZE;\n\t\tremaining -= AES_BLOCK_SIZE;\n\t\tdecrypted++;\n\t}\n\tif (remaining != 0) {\n\t\tdecrypted = decrypted * AES_BLOCK_SIZE;\n\t\tmemcpy(dstaddr, srcaddr, remaining);\n\t}\n}\n\n/*\n * Identifies correct key for decryption (if not previously identified) and decrypts data\n * The comparison function is selected from the passed file type\n * For EPK comparison, outType is used to store the detected type (EPK v2 or EPK v3)\n */\nint wrap_decryptimage(void *src, size_t datalen, void *dest, char *config_dir, FILE_TYPE_T type, FILE_TYPE_T *outType){\n\tCompareFunc compareFunc = NULL;\n\tswitch(type){\n\t\tcase EPK:\n\t\t\tcompareFunc = compare_epak_header;\n\t\t\tbreak;\n\t\tcase EPK_V2:\n\t\t\tcompareFunc = compare_epk2_header;\n\t\t\tbreak;\n\t\tcase PAK_V2:\n\t\t\tcompareFunc = compare_pak2_header;\n\t\t\tbreak;\n\t\tcase EPK_V3:\n\t\t\tcompareFunc = compare_epk3_header;\n\t\t\tbreak;\n\t}\n\n\tint decrypted = 0;\n\tuint8_t *decryptedData = NULL;\n\n\t// Check if we need decryption\n\tif(type != RAW && compareFunc(src, datalen)){\n\t\tdecrypted = 1;\n\t\treturn decrypted;\n\t}\n\n\tif(!keyFound){\n\t\tprintf(\"Trying known AES keys...\\n\");\n\t\tKeyPair *keyPair = find_AES_key(src, datalen, compareFunc, KEY_ECB, (void **)&decryptedData, 1);\n\t\tdecrypted = keyFound = (keyPair != NULL);\n\t\tif(decrypted){\n\t\t\taesKey = &(keyPair->key);\n\t\t}\n\t\tif(decrypted && type != EPK){\n\t\t\tmemcpy(dest, decryptedData, datalen);\n\t\t\tfree(decryptedData);\n\t\t}\n\t} else {\n\t\tdecryptImage(src, datalen, dest);\n\t\tif(type == RAW)\n\t\t\tdecrypted = 1;\n\t\telse\n\t\t\tdecrypted = compareFunc(dest, datalen);\n\t}\n\tif (!decrypted){\n\t\tPERROR(\"Cannot decrypt EPK content (proper AES key is missing).\\n\");\n\t\treturn -1;\n\t} else if(type == EPK){\n\t\tif(outType != NULL){\n\t\t\t*outType = compare_epak_header(decryptedData, datalen);\n\t\t}\n\t}\n\n\treturn decrypted;\n}\n\n/*\n * Verifies if a string contains 2 dots and numbers (x.y.z)\n */\nbool isEpkVersionString(const char *str){\n\t// Size of string is the same across EPK2 and EPK3, for both Platform and SDK versions\n\treturn count_tokens(str, '.', member_size(struct epk2_structure, platformVersion)) == 2;\n}\n\n/*\n * Detects if the EPK file is v2 or v3, and extracts it\n */\nvoid extractEPKfile(const char *epk_file, config_opts_t *config_opts){\n\tdo {\n\t\tMFILE *epk = mopen_private(epk_file, O_RDONLY);\n\t\tif(!epk){\n\t\t\terr_exit(\"\\nCan't open file %s\\n\\n\", epk_file);\n\t\t}\n\t\t//Make it R/W\n\t\tmprotect(epk->pMem, msize(epk), PROT_READ | PROT_WRITE);\n\n\t\tprintf(\"File size: %d bytes\\n\", msize(epk));\n\n\t\tstruct epk2_structure *epk2 = mdata(epk, struct epk2_structure);\n\t\tEPK_V2_HEADER_T *epkHeader = &(epk2->epkHeader);\n\n\t\tint result;\n\t\tFILE_TYPE_T epkType;\n\t\tif(compare_epk2_header((uint8_t *)epkHeader, sizeof(*epkHeader))){\n\t\t\tepkType = EPK_V2;\n\t\t} else {\n\t\t\tprintf(\"\\nTrying to decrypt EPK header...\\n\");\n\t\t\t/* Detect if the file is EPK v2 or EPK v3 */\n\t\t\tresult = wrap_decryptimage(\n\t\t\t\tepkHeader,\n\t\t\t\tsizeof(EPK_V2_HEADER_T),\n\t\t\t\tepkHeader,\n\t\t\t\tconfig_opts->config_dir,\n\t\t\t\tEPK,\n\t\t\t\t&epkType\n\t\t\t);\n\t\t\tif(result < 0){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tswitch(epkType){\n\t\t\tcase EPK_V2:\n\t\t\t\tprintf(\"[+] EPK v2 Detected\\n\");\n\t\t\t\textractEPK2(epk, config_opts);\n\t\t\t\tbreak;\n\t\t\tcase EPK_V3:\n\t\t\tcase EPK_V3_NEW:\n\t\t\t\tprintf(\"[+] EPK v3 Detected\\n\");\n\t\t\t\textractEPK3(epk, epkType, config_opts);\n\t\t\t\tbreak;\n\t\t}\n\t} while(0);\n}\n"
  },
  {
    "path": "src/epk1.c",
    "content": "/**\n * EPK v1 handling\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * Copyright 20?? sirius\n * All right reserved\n */\n#include <unistd.h>\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <errno.h>\n\n#include \"main.h\" //for handle_file\n#include \"epk1.h\"\n#include \"os_byteswap.h\"\n#include \"util.h\"\n\n#define PAKNAME_LEN 4\n\nbool isFileEPK1(const char *epk_file) {\n\tFILE *file = fopen(epk_file, \"rb\");\n\tif (file == NULL) {\n\t\terr_exit(\"Can't open file %s\\n\\n\", epk_file);\n\t}\n\n\tchar magic[4];\n\tsize_t nRead = fread(&magic, 1, 4, file);\n\tfclose(file);\n\n\tif (nRead != 4) {\n\t\treturn 0;\n\t}\n\n\tif (memcmp(&magic, \"epak\", 4) == 0) {\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n}\n\nvoid printHeaderInfo(struct epk1Header_t *epakHeader) {\n\tprintf(\"\\nFirmware otaID: %s\\n\", epakHeader->otaID);\n\tprintf(\"Firmware version: \" EPKV1_VERSION_FORMAT \"\\n\", epakHeader->fwVer[2], epakHeader->fwVer[1], epakHeader->fwVer[0]);\n\tprintf(\"PAK count: %d\\n\", epakHeader->pakCount);\n\tprintf(\"PAKs total size: %d\\n\", epakHeader->fileSize);\n}\n\nvoid printNewHeaderInfo(struct epk1NewHeader_t *epakHeader) {\n\tprintf(\"\\nFirmware otaID: %s\\n\", epakHeader->otaID);\n\tprintf(\"Firmware version: \" EPKV1_VERSION_FORMAT \"\\n\", epakHeader->fwVer[2], epakHeader->fwVer[1], epakHeader->fwVer[0]);\n\tprintf(\"PAK count: %d\\n\", epakHeader->pakCount);\n\tprintf(\"PAKs total size: %d\\n\", epakHeader->fileSize);\n}\n\nvoid constructVerString(char *fw_version, struct epk1Header_t *epakHeader) {\n\tsprintf(fw_version, EPKV1_VERSION_FORMAT \"-%s\", epakHeader->fwVer[2], epakHeader->fwVer[1], epakHeader->fwVer[0], epakHeader->otaID);\n}\n\nvoid constructNewVerString(char *fw_version, struct epk1NewHeader_t *epakHeader) {\n\tsprintf(fw_version, EPKV1_VERSION_FORMAT \"-%s\", epakHeader->fwVer[2], epakHeader->fwVer[1], epakHeader->fwVer[0], epakHeader->otaID);\n}\n\nvoid extract_epk1_file(const char *epk_file, config_opts_t *config_opts) {\n\tint file;\n\tif ((file = open(epk_file, O_RDONLY)) == -1) {\n\t\terr_exit(\"\\nCan't open file %s\\n\\n\", epk_file);\n\t}\n\n\tstruct stat statbuf;\n\tif (fstat(file, &statbuf) == -1) {\n\t\terr_exit(\"\\nfstat error\\n\\n\");\n\t}\n\n\tint fileLength = statbuf.st_size;\n\tprintf(\"File size: %d bytes\\n\", fileLength);\n\n\tvoid *buffer;\n\tif ((buffer = mmap(0, fileLength, PROT_READ, MAP_SHARED, file, 0)) == MAP_FAILED) {\n\t\terr_exit(\"\\nCannot mmap input file (%s). Aborting\\n\\n\", strerror(errno));\n\t}\n\n\tchar verString[12];\n\tint index;\n\tuint32_t pakcount = ((struct epk1Header_t *)buffer)->pakCount;\n\tif (pakcount >> 8 != 0) {\n\t\tSWAP(pakcount);\n\t\tprintf(\"\\nFirmware type is EPK1 Big Endian...\\n\");\n\n\t\tunsigned char *header = malloc(sizeof(struct epk1BEHeader_t));\t//allocate space for header\n\t\tmemcpy(header, buffer, sizeof(struct epk1BEHeader_t));\t//copy header to buffer\n\n\t\tstruct epk1BEHeader_t *epakHeader = (struct epk1BEHeader_t *)header;\t//make struct from buffer\n\t\tSWAP(epakHeader->fileSize);\n\t\tSWAP(epakHeader->pakCount);\n\t\tSWAP(epakHeader->offset);\n\n\t\tprintf(\"\\nFirmware otaID: %s\\n\", (char *)(buffer + epakHeader->offset + 8));\n\n\t\tstruct epk1BEVersion_t *fwVer = buffer + epakHeader->offset - 4;\n\n\t\tif (fwVer->pad != 0) {\n\t\t\tprintf(\"Note: Padding byte is not zero (0x%\" PRIx8 \")!\\n\", fwVer->pad);\n\t\t}\n\n\t\tsprintf(verString, EPKV1_VERSION_FORMAT, fwVer->major, fwVer->minor1, fwVer->minor2);\n\t\tprintf(\"Firmware version: %s\\n\", verString);\n\t\tprintf(\"PAK count: %d\\n\", epakHeader->pakCount);\n\t\tprintf(\"PAKs total size: %d\\n\", epakHeader->fileSize);\n\n\t\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, verString);\n\t\tcreateFolder(config_opts->dest_dir);\n\n\t\tunsigned long int offset = 0xC;\n\t\tfor (index = 0; index < epakHeader->pakCount; index++) {\n\t\t\tstruct pakRec_t *pakRecord = malloc(sizeof(struct pakRec_t));\t//allocate space for header\n\t\t\tif (pakRecord == NULL) {\n\t\t\t\terr_exit(\"Error in %s: malloc() failed\\n\", __func__);\n\t\t\t}\n\t\t\tmemcpy(pakRecord, buffer + offset, sizeof(struct pakRec_t));\t//copy pakRecord to buffer\n\n\t\t\tif (pakRecord->offset == 0) {\n\t\t\t\toffset += 8;\n\t\t\t\tindex--;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tSWAP(pakRecord->offset);\n\t\t\tSWAP(pakRecord->size);\n\t\t\tunsigned char *pheader = malloc(sizeof(struct pakHeader_t));\n\t\t\tif (pheader == NULL) {\n\t\t\t\terr_exit(\"Error in %s: malloc() failed\\n\", __func__);\n\t\t\t}\n\t\t\tmemcpy(pheader, (buffer + pakRecord->offset), sizeof(struct pakHeader_t));\n\t\t\tstruct pakHeader_t *pakHeader = (struct pakHeader_t *)pheader;\n\t\t\tSWAP(pakHeader->pakSize);\n\t\t\tpakHeader = (struct pakHeader_t *)(buffer + pakRecord->offset);\n\n\t\t\tchar pakName[PAKNAME_LEN + 1] = \"\";\n\t\t\tsprintf(pakName, \"%.*s\", PAKNAME_LEN, pakHeader->pakName);\n\n\t\t\tchar filename[PATH_MAX + 1] = \"\";\n\t\t\tint filename_len = snprintf(filename, PATH_MAX + 1, \"%s/%s.pak\", config_opts->dest_dir, pakName);\n\n\t\t\tif (filename_len > PATH_MAX) {\n\t\t\t\terr_exit(\"Error in %s: filename too long (%d > %d)\\n\", __func__, filename_len, PATH_MAX);\n\t\t\t} else if (filename_len < 0) {\n\t\t\t\terr_exit(\"Error in %s: snprintf() failed (%d)\\n\", __func__, filename_len);\n\t\t\t}\n\n\t\t\tprintf(\"\\n#%u/%u saving PAK (name='%s', platform='%s', offset=0x%x, size='%d') to file %s\\n\", index + 1, epakHeader->pakCount, pakName, pakHeader->platform, pakRecord->offset, pakRecord->size, filename);\n\t\t\tFILE *outfile = fopen(filename, \"wb\");\n\n\t\t\tif (outfile == NULL) {\n\t\t\t\terr_exit(\"Error in %s: failed to open file '%s': %s.\\n\", __func__, filename, strerror(errno));\n\t\t\t}\n\n\t\t\tfwrite(pakHeader->pakName + sizeof(struct pakHeader_t), 1, pakRecord->size - 132, outfile);\n\t\t\tfclose(outfile);\n\n\t\t\thandle_file(filename, config_opts);\n\t\t\tfree(pakRecord);\n\t\t\tfree(pheader);\n\t\t\toffset += 8;\n\t\t}\n\n\t\tfree(header);\n\t} else if (pakcount < 21) {\t// old EPK1 header\n\t\tprintf(\"\\nFirmware type is EPK1...\\n\");\n\t\tstruct epk1Header_t *epakHeader = (struct epk1Header_t *)buffer;\n\t\tprintHeaderInfo(epakHeader);\n\t\tconstructVerString(verString, epakHeader);\n\t\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, verString);\n\t\tcreateFolder(config_opts->dest_dir);\n\n\t\tfor (index = 0; index < epakHeader->pakCount; index++) {\n\t\t\tstruct pakRec_t pakRecord = epakHeader->pakRecs[index];\n\t\t\tstruct pakHeader_t *pakHeader;\n\t\t\tpakHeader = (struct pakHeader_t *)(buffer + pakRecord.offset);\n\n\t\t\tchar pakName[PAKNAME_LEN + 1] = \"\";\n\t\t\tsprintf(pakName, \"%.*s\", PAKNAME_LEN, pakHeader->pakName);\n\n\t\t\tchar filename[PATH_MAX + 1] = \"\";\n\t\t\tint filename_len = snprintf(filename, PATH_MAX + 1, \"%s/%s.pak\", config_opts->dest_dir, pakName);\n\n\t\t\tif (filename_len > PATH_MAX) {\n\t\t\t\terr_exit(\"Error in %s: filename too long (%d > %d)\\n\", __func__, filename_len, PATH_MAX);\n\t\t\t} else if (filename_len < 0) {\n\t\t\t\terr_exit(\"Error in %s: snprintf() failed (%d)\\n\", __func__, filename_len);\n\t\t\t}\n\n\t\t\tprintf(\"\\n#%u/%u saving PAK (name='%s', platform='%s', offset=0x%x, size='%d') to file %s\\n\", index + 1, epakHeader->pakCount, pakName, pakHeader->platform, pakRecord.offset, pakRecord.size, filename);\n\t\t\tFILE *outfile = fopen(((const char *)filename), \"wb\");\n\n\t\t\tif (outfile == NULL) {\n\t\t\t\terr_exit(\"Error in %s: failed to open file '%s': %s.\\n\", __func__, filename, strerror(errno));\n\t\t\t}\n\n\t\t\tfwrite(pakHeader->pakName + sizeof(struct pakHeader_t), 1, pakRecord.size - 132, outfile);\n\t\t\tfclose(outfile);\n\n\t\t\thandle_file(filename, config_opts);\n\t\t}\n\t} else {\t\t\t\t\t// new EPK1 header\n\t\tprintf(\"\\nFirmware type is EPK1(new)...\\n\");\n\t\tstruct epk1NewHeader_t *epakHeader = (struct epk1NewHeader_t *)(buffer);\n\t\tprintNewHeaderInfo(epakHeader);\n\t\tconstructNewVerString(verString, epakHeader);\n\t\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, verString);\n\t\tcreateFolder(config_opts->dest_dir);\n\n\t\tfor (index = 0; index < epakHeader->pakCount; index++) {\n\t\t\tstruct pakRec_t pakRecord = epakHeader->pakRecs[index];\n\t\t\tstruct pakHeader_t *pakHeader = (struct pakHeader_t *)(buffer + pakRecord.offset);\n\n\t\t\tchar pakName[PAKNAME_LEN + 1] = \"\";\n\t\t\tsprintf(pakName, \"%.*s\", PAKNAME_LEN, pakHeader->pakName);\n\n\t\t\tchar filename[PATH_MAX + 1] = \"\";\n\t\t\tint filename_len = snprintf(filename, PATH_MAX + 1, \"%s/%s.pak\", config_opts->dest_dir, pakName);\n\n\t\t\tif (filename_len > PATH_MAX) {\n\t\t\t\terr_exit(\"Error in %s: filename too long (%d > %d)\\n\", __func__, filename_len, PATH_MAX);\n\t\t\t} else if (filename_len < 0) {\n\t\t\t\terr_exit(\"Error in %s: snprintf() failed (%d)\\n\", __func__, filename_len);\n\t\t\t}\n\n\t\t\tprintf(\"\\n#%u/%u saving PAK (name='%s', platform='%s', offset=0x%x, size='%d') to file %s\\n\", index + 1, epakHeader->pakCount, pakName, pakHeader->platform, pakRecord.offset, pakRecord.size, filename);\n\t\t\tFILE *outfile = fopen(filename, \"wb\");\n\n\t\t\tif (outfile == NULL) {\n\t\t\t\terr_exit(\"Error in %s: failed to open file '%s': %s.\\n\", __func__, filename, strerror(errno));\n\t\t\t}\n\n\t\t\tfwrite(pakHeader->pakName + sizeof(struct pakHeader_t), 1, pakHeader->pakSize + 4, outfile);\n\t\t\tfclose(outfile);\n\n\t\t\thandle_file(filename, config_opts);\n\t\t}\n\t}\n\n\tif (munmap(buffer, fileLength) == -1) {\n\t\tprintf(\"Error un-mmapping the file\");\n\t}\n\n\tclose(file);\n}\n"
  },
  {
    "path": "src/epk2.c",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <crc.h>\n#include <dirent.h>\n#include <ctype.h>\n\n#include \"config.h\"\n#include \"common.h\"\n#include \"main.h\" /* handle_file */\n\n#include \"epk.h\"\n#include \"epk2.h\"\n\n#include \"mfile.h\"\n#include \"util.h\"\n#include \"util_crypto.h\"\n\n/*\n * Checks if the given data is a PAK2 header\n */\nint compare_pak2_header(uint8_t *header, size_t headerSize){\n\tPAK_V2_HEADER_T *hdr = (PAK_V2_HEADER_T *)header;\n\treturn memcmp(hdr->pakMagic, PAK_MAGIC, sizeof(hdr->pakMagic)) == 0;\n}\n\n/*\n * Checks if the given data is an EPK2 header\n */\nint compare_epk2_header(uint8_t *header, size_t headerSize){\n\tEPK_V2_HEADER_T *hdr = (EPK_V2_HEADER_T *)header;\n\treturn memcmp(hdr->epkMagic, EPK2_MAGIC, sizeof(hdr->epkMagic)) == 0;\n}\n\nMFILE *isFileEPK2(const char *epk_file) {\n\tsetKeyFile_LG();\n\tMFILE *file = mopen(epk_file, O_RDONLY);\n\tif (!file) {\n\t\terr_exit(\"Can't open file %s\\n\\n\", epk_file);\n\t}\n\n\tstruct epk2_structure *epk2 = mdata(file, struct epk2_structure);\n\n\tif(msize(file) < sizeof(*epk2)){\n\t\tgoto checkFail;\n\t}\n\n\t// check if the epk magic is present (decrypted)\n\tif(compare_epk2_header((uint8_t *)&(epk2->epkHeader), sizeof(EPK_V2_HEADER_T))){\n\t\tgoto checkOk;\n\t}\n\n\tbool has_versions = false;\n\tif(isEpkVersionString(epk2->platformVersion) && isEpkVersionString(epk2->sdkVersion)){\n\t\thas_versions = true;\n\t\tgoto checkOk;\n\t}\n\n\tcheckFail:\n\t\tmclose(file);\n\t\treturn NULL;\n\n\tcheckOk:\n\t\tif(has_versions){\n\t\t\tprintf(\"[EPK2] Platform Version: %.*s\\n\", sizeof(epk2->platformVersion), epk2->platformVersion);\n\t\t\tprintf(\"[EPK2] SDK Version: %.*s\\n\", sizeof(epk2->sdkVersion), epk2->sdkVersion);\n\t\t}\n\t\treturn file;\n\n}\n\nvoid extractEPK2(MFILE *epk, config_opts_t *config_opts) {\n\tstruct epk2_structure *epk2 = mdata(epk, struct epk2_structure);\n\tEPK_V2_HEADER_T *epkHeader = &(epk2->epkHeader);\n\tint result;\n\n\tif(config_opts->enableSignatureChecking){\n\t\tsize_t signed_size = (\n\t\t\tmember_size(struct epk2_structure, epkHeader) +\n\t\t\tmember_size(struct epk2_structure, crc32Info)\n\t\t);\n\n\t\t/**\n\t\t * Note:\n\t\t * The signature check is not strict but tries the given size and\n\t\t * tries with smaller sizes if unsuccesful.\n\t\t * This allows us to work with EPK2 headers of different size by using\n\t\t * the biggest header as base (64 partitions)\n\t\t */\n\t\tprintf(\"\\nVerifying digital signature of EPK2 firmware header...\\n\");\n\t\tresult = wrap_verifyimage(\n\t\t\t// Signature to check against\n\t\t\tepk2->signature,\n\t\t\t// Header to verify\n\t\t\tepkHeader,\n\t\t\tsigned_size,\n\t\t\t// Folder containing keys\n\t\t\tconfig_opts->config_dir,\n\t\t\tSIG_SHA1\n\t\t);\n\t}\n\n\tif (config_opts->signatureOnly)\n\t\treturn;\n\n\tresult = wrap_decryptimage(\n\t\tepkHeader,\n\t\tsizeof(EPK_V2_HEADER_T),\n\t\tepkHeader,\n\t\tconfig_opts->dest_dir,\n\t\tEPK_V2,\n\t\tNULL\n\t);\n\n\tif(result < 0){\n\t\treturn;\n\t}\n\n\tPAK_V2_LOCATION_T *pakLocs = epkHeader->imageLocation;\n\n\tprintf(\"\\nFirmware info\\n\");\n\tprintf(\"-------------\\n\");\n\tprintf(\"Firmware magic: %.*s\\n\", 4, epkHeader->fileType);\n\tprintf(\"Firmware type: %.*s\\n\", 4, epkHeader->epkMagic);\n\tprintf(\"Firmware otaID: %s\\n\", epkHeader->otaId);\n\tprintf(\"Firmware version: \" EPK_VERSION_FORMAT \"\\n\",\n\t\tepkHeader->epakVersion[3],\n\t\tepkHeader->epakVersion[2],\n\t\tepkHeader->epakVersion[1],\n\t\tepkHeader->epakVersion[0]);\n\n\tprintf(\"PAK count: %d\\n\", epkHeader->fileNum);\n\tprintf(\"PAKs total size: %d\\n\", epkHeader->fileSize);\n\tprintf(\"Header length: %d\\n\\n\", pakLocs[0].imageOffset); //first image after header\n\n\tchar *fwVersion;\n\tasprintf(&fwVersion, EPK_VERSION_FORMAT \"-%s\",\n\t\tepkHeader->epakVersion[3],\n\t\tepkHeader->epakVersion[2],\n\t\tepkHeader->epakVersion[1],\n\t\tepkHeader->epakVersion[0],\n\t\tepkHeader->otaId\n\t);\n\n\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, fwVersion);\n\tcreateFolder(config_opts->dest_dir);\n\n\tunsigned int curPak=0, signatureCount=0;\n\tuintptr_t pakLoc;\n\n\tstruct pak2_structure *pak;\n\t/* Process every pak in a loop */\n\tfor(curPak=0; curPak < epkHeader->fileNum; curPak++){\n\t\tpakLoc = (uintptr_t)(epkHeader) + pakLocs[curPak].imageOffset + (sizeof(signature_t) * signatureCount);\n\t\tpak = (struct pak2_structure *)pakLoc;\n\n\t\tunsigned int curSeg, segCount;\n\t\tchar *filename;\n\t\tchar *pakPartitionShortName;\n\t\tMFILE *outFile;\n\n\t\t/* Process every segment in a loop. We don't know the segment count yet */\n\t\tfor (curSeg=0; ;){\n\t\t\t++signatureCount;\n\n\t\t\tsize_t signed_size = pakLocs[curPak].imageSize;\n\n\t\t\t/* if the package is splitted, fallback to the segment size */\n\t\t\tif(signed_size > pakLocs[curPak].segmentSize){\n\t\t\t\tsigned_size = pakLocs[curPak].segmentSize + sizeof(PAK_V2_HEADER_T);\n\n\t\t\t\t/*\n\t\t\t\t* We now need to check if the segment is trailing. If it is, we'd overflow into the next\n\t\t\t\t* package. Calculate the distance between us and the next package. If less than the segment size, truncate\n\t\t\t\t*/\n\t\t\t\tsize_t distance;\n\t\t\t\tstruct pak2_structure *nextPak = (struct pak2_structure *)(\n\t\t\t\t\t(uintptr_t)(epkHeader) + pakLocs[curPak + 1].imageOffset + (sizeof(signature_t) * signatureCount)\n\t\t\t\t);\n\n\t\t\t\t// No need to subtract signature, as it's included in both (so it cancels out)\n\t\t\t\tdistance = (size_t)(\n\t\t\t\t\t(uintptr_t)&(nextPak->pakHeader) - (uintptr_t)&(pak->pakHeader)\n\t\t\t\t);\n\n\t\t\t\t// Last pak will have a distance < than the segment size\n\t\t\t\t// Because the data contained is less\n\t\t\t\tif(distance < pakLocs[curPak].segmentSize){\n\t\t\t\t\tsigned_size = distance - sizeof(signature_t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(config_opts->enableSignatureChecking){\n\t\t\t\twrap_verifyimage(\n\t\t\t\t\tpak->signature,\n\t\t\t\t\t&(pak->pakHeader),\n\t\t\t\t\tsigned_size,\n\t\t\t\t\tconfig_opts->config_dir,\n\t\t\t\t\tSIG_SHA1\n\t\t\t\t);\n\t\t\t}\n\n\n\t\t\t//printf(\"Decrypting PAK Header @0x%x\\n\", (uintptr_t)&(pak->pakHeader)-(uintptr_t)epk2);\n\t\t\t//decrypt the pak header\n\t\t\tint result = wrap_decryptimage(\n\t\t\t\t\t&(pak->pakHeader),\n\t\t\t\t\tsizeof(PAK_V2_HEADER_T),\n\t\t\t\t\t&(pak->pakHeader),\n\t\t\t\t\tconfig_opts->config_dir,\n\t\t\t\t\t(FILE_TYPE_T)PAK_V2,\n\t\t\t\t\tNULL\n\t\t\t);\n\n\t\t\tif(result < 0){\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcurSeg = pak->pakHeader.segmentIndex;\n\t\t\tsegCount = pak->pakHeader.segmentCount;\n\t\t\tif(curSeg == 0){ //first pak, print segment count and open output file\n\t\t\t\tprintf(\"\\nPAK '%.4s' contains %d segment(s):\\n\", pak->pakHeader.imageType, pak->pakHeader.segmentCount);\n\t\t\t\tpakPartitionShortName = pak->pakHeader.imageType;\n\t\t\t\tasprintf(&filename, \"%s/%.4s.pak\", config_opts->dest_dir, pak->pakHeader.imageType);\n\n\t\t\t\toutFile = mfopen(filename, \"w+\");\n\t\t\t\tif(!outFile){\n\t\t\t\t\tPERROR_SE(\"Cannot open %s for writing\", filename);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmfile_map(outFile, pak->pakHeader.imageSize);\n\t\t\t}\n\n\t\t\tsize_t pakContentSize = pak->pakHeader.segmentSize;\n\n\t\t\t//printf(\"Decrypting PAK DATA @0x%x\\n\", (uintptr_t)pak-(uintptr_t)epk2);\n\t\t\t//decrypt the pak data\n\t\t\twrap_decryptimage(\n\t\t\t\t&(pak->pData),\n\t\t\t\tpak->pakHeader.segmentSize,\n\t\t\t\t&(pak->pData),\n\t\t\t\tconfig_opts->config_dir,\n\t\t\t\t(FILE_TYPE_T)RAW,\n\t\t\t\tNULL\n\t\t\t);\n\n\t\t\tmwrite(&(pak->pData), pakContentSize, 1, outFile); //write the decrypted data\n\n\n\t\t\tprintf(\"  segment #%u (name='%.4s',\", curSeg + 1, pak->pakHeader.imageType);\n\t\t\tprintf(\" version='%02x.%02x.%02x.%02x',\",\n\t\t\t\t(pak->pakHeader.swVersion >> 24) & 0xff,\n\t\t\t\t(pak->pakHeader.swVersion >> 16) & 0xff,\n\t\t\t\t(pak->pakHeader.swVersion >> 8 ) & 0xff,\n\t\t\t\t(pak->pakHeader.swVersion      ) & 0xff);\n\t\t\tprintf(\" platform='%s', offset='0x%x', size='%u bytes', \",\n\t\t\t\tpak->pakHeader.modelName,\n\t\t\t\tmoff(epk, pak),\n\t\t\t\tpakContentSize);\n\n\t\t\tswitch ((BUILD_TYPE_T) pak->pakHeader.devMode) {\n\t\t\t\tcase RELEASE:\n\t\t\t\t\tprintf(\"build=RELEASE\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase DEBUG:\n\t\t\t\t\tprintf(\"build=DEBUG\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase TEST:\n\t\t\t\t\tprintf(\"build=TEST\");\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tprintf(\"build=UNKNOWN 0x%x\\n\", pak->pakHeader.devMode);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprintf(\")\\n\");\n\n\t\t\tif(curSeg + 1 == segCount){\n\t\t\t\tprintf(\"#%u/%u saved PAK (%.4s) to file %s\\n\",\n\t\t\t\t\tcurPak + 1, epkHeader->fileNum,\n\t\t\t\t\tpakPartitionShortName, filename);\n\t\t\t\tmclose(outFile);\n\t\t\t\thandle_file(filename, config_opts);\n\t\t\t\tfree(filename);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmfile_flush(&(pak->pData), pak->pakHeader.segmentSize);\n\n\t\t\tpakLoc += sizeof(*pak) + pakContentSize;\n\t\t\tpak = (struct pak2_structure *)pakLoc;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/epk3.c",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"main.h\"\n#include \"config.h\"\n#include \"mfile.h\"\n#include \"epk3.h\"\n#include \"util.h\"\n#include \"util_crypto.h\"\n\n/*\n * Check for epk3 files with an additional heading signature (whole file signature?)\n */\nint compare_epk3_new_header(uint8_t *header, size_t headerSize){\n\tEPK_V3_HEADER_T *hdr = (EPK_V3_HEADER_T *)(header + SIGNATURE_SIZE);\n\treturn memcmp(hdr->epkMagic, EPK3_MAGIC, sizeof(hdr->epkMagic)) == 0;\n}\n\n/*\n * Checks if the given data is an EPK3 header\n */\nint compare_epk3_header(uint8_t *header, size_t headerSize){\n\tEPK_V3_HEADER_T *hdr = (EPK_V3_HEADER_T *)header;\n\n\treturn memcmp(hdr->epkMagic, EPK3_MAGIC, sizeof(hdr->epkMagic)) == 0;\n}\n\nMFILE *isFileEPK3(const char *epk_file) {\n\tsetKeyFile_LG();\n\tMFILE *file = mopen(epk_file, O_RDONLY);\n\tif (!file) {\n\t\terr_exit(\"Can't open file %s\\n\\n\", epk_file);\n\t}\n\n\tstruct epk3_structure *epk3 = mdata(file, struct epk3_structure);\n\tstruct epk3_head_structure *head = &(epk3->head);\n\n\tif(msize(file) < sizeof(*epk3)){\n\t\tgoto checkFail;\n\t}\n\n\t// check if the epk magic is present (decrypted)\n\tif(compare_epk3_header((uint8_t *)&(head->epkHeader), sizeof(EPK_V3_HEADER_T))){\n\t\tgoto checkOk;\n\t}\n\n\tif(isEpkVersionString(head->platformVersion) && isEpkVersionString(head->sdkVersion))\n\t\tgoto checkOk;\n\n\n\tcheckFail:\n\t\tmclose(file);\n\t\treturn NULL;\n\n\tcheckOk:\n\t\tprintf(\"[EPK3] Platform Version: %.*s\\n\", sizeof(head->platformVersion), head->platformVersion);\n\t\tprintf(\"[EPK3] SDK Version: %.*s\\n\", sizeof(head->sdkVersion), head->sdkVersion);\n\t\treturn file;\n}\n\nvoid extractEPK3(MFILE *epk, FILE_TYPE_T epkType, config_opts_t *config_opts){\n\n\tepk3_union *epk3 = mdata(epk, epk3_union);\n\n\tsize_t headerSize, signed_size, sigSize, extraSegmentSize;\n\tSIG_TYPE_T sigType;\n\t{\n\t\tswitch(epkType){\n\t\t\tcase EPK_V3:\n\t\t\t\theaderSize = sizeof(EPK_V3_HEADER_T);\n\t\t\t\tsigned_size = (\n\t\t\t\t\tsizeof(epk3->old.head.epkHeader) +\n\t\t\t\t\tsizeof(epk3->old.head.crc32Info) +\n\t\t\t\t\tsizeof(epk3->old.head.reserved)\n\t\t\t\t);\n\t\t\t\tsigType = SIG_SHA1;\n\t\t\t\tsigSize = SIGNATURE_SIZE;\n\t\t\t\textraSegmentSize = 0;\n\t\t\t\tbreak;\n\t\t\tcase EPK_V3_NEW:\n\t\t\t\theaderSize = sizeof(EPK_V3_NEW_HEADER_T);\n\t\t\t\tsigned_size = headerSize;\n\t\t\t\tsigType = SIG_SHA256;\n\t\t\t\tsigSize = SIGNATURE_SIZE_NEW;\n\t\t\t\t/* each segment has an index value */\n\t\t\t\textraSegmentSize = sizeof(uint32_t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\terr_exit(\"Unsupported EPK3 variant\\n\");\n\t\t}\n\t}\n\n\tEPK_V3_HEADER_UNION *epkHeader;\n\n\tif (epkType == EPK_V3_NEW) {\n\t\tepkHeader = (EPK_V3_HEADER_UNION *) &(epk3->new.head.epkHeader);\n\t} else {\n\t\tepkHeader = (EPK_V3_HEADER_UNION *) &(epk3->old.head.epkHeader);\n\t}\n\n\tif(config_opts->enableSignatureChecking)\n\t{\n\t\twrap_verifyimage(\n\t\t\tepk3->old.head.signature,\t/* same offset in old/new */\n\t\t\tepkHeader,\n\t\t\tsigned_size,\n\t\t\tconfig_opts->config_dir,\n\t\t\tsigType\n\t\t);\n\t}\n\n\tint result = wrap_decryptimage(\n\t\tepkHeader,\n\t\theaderSize,\n\t\tepkHeader,\n\t\tconfig_opts->dest_dir,\n\t\tEPK_V3,\n\t\tNULL\n\t);\n\n\tif(result < 0){\n\t\treturn;\n\t}\n\n\tsize_t pak_signed_size;\n\tPAK_V3_LISTHEADER_UNION *packageInfo;\n\n\tPAK_V3_HEADER_T *pak;\n\n\tvoid *sigPtr;\n\n\tswitch(epkType){\n\t\tcase EPK_V3:\n\t\t\tpak_signed_size = epkHeader->old.packageInfoSize;\n\t\t\tpackageInfo = (PAK_V3_LISTHEADER_UNION *) &(epk3->old.packageInfo);\n\t\t\tpak = &(packageInfo->old.packages[0]);\n\t\t\tsigPtr = epk3->old.packageInfo_signature;\n\t\t\tbreak;\n\t\tcase EPK_V3_NEW:\n\t\t\tpak_signed_size = epkHeader->new.packageInfoSize;\n\t\t\tpackageInfo = (PAK_V3_LISTHEADER_UNION *) &(epk3->new.packageInfo);\n\t\t\tpak = &(packageInfo->new.packages[0]);\n\t\t\tsigPtr = epk3->new.packageInfo_signature;\n\t\t\tbreak;\n\t}\n\n\tif(config_opts->enableSignatureChecking){\n\t\twrap_verifyimage(\n\t\t\tsigPtr,\n\t\t\tpackageInfo,\n\t\t\tpak_signed_size,\n\t\t\tconfig_opts->config_dir,\n\t\t\tsigType\n\t\t);\n\t}\n\n\tprintf(\"\\nFirmware info\\n\");\n\tprintf(\"-------------\\n\");\n\tprintf(\"Firmware magic: %.*s\\n\", 4, epkHeader->old.epkMagic);\n\tprintf(\"Firmware otaID: %s\\n\", epkHeader->old.otaId);\n\tprintf(\"Firmware version: \" EPK_VERSION_FORMAT \"\\n\",\n\t\tepkHeader->old.epkVersion[3],\n\t\tepkHeader->old.epkVersion[2],\n\t\tepkHeader->old.epkVersion[1],\n\t\tepkHeader->old.epkVersion[0]\n\t);\n\tprintf(\"packageInfoSize: %d\\n\", epkHeader->old.packageInfoSize);\n\tprintf(\"bChunked: %d\\n\", epkHeader->old.bChunked);\n\n\tif(epkType == EPK_V3_NEW){\n\t\tprintf(\"EncryptType: %.*s\\n\",\n\t\t\tsizeof(epkHeader->new.encryptType),\n\t\t\tepkHeader->new.encryptType\n\t\t);\n\t\tprintf(\"UpdateType:  %.*s\\n\",\n\t\t\tsizeof(epkHeader->new.updateType),\n\t\t\tepkHeader->new.updateType\n\t\t);\n\t\tprintf(\"unknown: %02hhx %02hhx %02hhx\\n\", epkHeader->new.gap[0], epkHeader->new.gap[1], epkHeader->new.gap[2]);\n\t\tprintf(\"updatePlatformVersion: %f\\n\", epkHeader->new.updatePlatformVersion);\n\t\tprintf(\"compatibleMinimumVersion: %f\\n\", epkHeader->new.compatibleMinimumVersion);\n\t\tprintf(\"needToCheckCompatibleVersion: %d\\n\", epkHeader->new.needToCheckCompatibleVersion);\n\t}\n\n\tif (config_opts->signatureOnly)\n\t\treturn;\n\n\tchar *fwVersion;\n\tasprintf(&fwVersion, EPK_VERSION_FORMAT \"-%s\",\n\t\tepkHeader->old.epkVersion[3],\n\t\tepkHeader->old.epkVersion[2],\n\t\tepkHeader->old.epkVersion[1],\n\t\tepkHeader->old.epkVersion[0],\n\t\tepkHeader->old.otaId\n\t);\n\n\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, fwVersion);\n\n\tcreateFolder(config_opts->dest_dir);\n\tfree(fwVersion);\n\n\tprintf(\"---- begin ----\\n\");\n\n\n\t/* Decrypt packageInfo */\n\tresult = wrap_decryptimage(\n\t\tpackageInfo,\n\t\tepkHeader->old.packageInfoSize,\n\t\tpackageInfo,\n\t\tconfig_opts->dest_dir,\n\t\tRAW,\n\t\tNULL\n\t);\n\n\tif(result < 0){\n\t\treturn;\n\t}\n\n\tif(epkType == EPK_V3_NEW){\n\t\tif(packageInfo->new.pakInfoMagic != epkHeader->new.pakInfoMagic){\n\t\t\tprintf(\"pakInfoMagic mismatch! (expected: %04X, actual: %04X)\\n\",\n\t\t\t\t\tepkHeader->new.pakInfoMagic,\n\t\t\t\t\tpackageInfo->new.pakInfoMagic\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tuintptr_t dataPtr = (uintptr_t)packageInfo;\n\n\tdataPtr += epkHeader->old.packageInfoSize;\n\n\tint packageInfoCount;\n\n\tswitch(epkType){\n\t\tcase EPK_V3:\n\t\t\tpackageInfoCount = packageInfo->old.packageInfoCount;\n\t\t\tbreak;\n\t\tcase EPK_V3_NEW:\n\t\t\tpackageInfoCount = packageInfo->new.packageInfoCount;\n\t\t\tbreak;\n\t}\n\n\tfor(uint i = 0; i<packageInfoCount;){\n\t\tif(pak->packageInfoSize != sizeof(*pak)){\n\t\t\tprintf(\"Warning: Unexpected packageInfoSize '%d', expected '%d'\\n\",\n\t\t\t\t\tpak->packageInfoSize, sizeof(*pak)\n\t\t\t);\n\t\t}\n\n\t\tprintf(\"\\nPAK '%s' contains %d segment(s), size %d bytes:\\n\",\n\t\t\tpak->packageName,\n\t\t\tpak->segmentInfo.segmentCount,\n\t\t\tpak->packageSize\n\t\t);\n\n\t\tchar *pakFileName;\n\t\tasprintf(&pakFileName, \"%s/%s.pak\", config_opts->dest_dir, pak->packageName);\n\n\t\tMFILE *pakFile = mfopen(pakFileName, \"w+\");\n\t\tif(!pakFile){\n\t\t\terr_exit(\"Cannot open '%s' for writing\\n\", pakFileName);\n\t\t}\n\t\tmfile_map(pakFile, pak->packageSize);\n\t\tprintf(\"Saving partition (%s) to file %s\\n\", pak->packageName, pakFileName);\n\n\n\t\tPACKAGE_SEGMENT_INFO_T segmentInfo = pak->segmentInfo;\n\t\tuint segNo;\n\t\tfor(segNo = segmentInfo.segmentIndex;\n\t\t\tsegNo < segmentInfo.segmentCount;\n\t\t\tsegNo++, pak++, i++\n\t\t){\n\t\t\tdataPtr += sigSize;\n\n\t\t\tif(config_opts->enableSignatureChecking)\n\t\t\t{\n\t\t\t\twrap_verifyimage(\n\t\t\t\t\t(void *)(dataPtr - sigSize),\n\t\t\t\t\t(void *)dataPtr,\n\t\t\t\t\tpak->segmentInfo.segmentSize + extraSegmentSize,\n\t\t\t\t\tconfig_opts->config_dir,\n\t\t\t\t\tsigType\n\t\t\t\t);\n\t\t\t}\n\n\n\t\t\tprintf(\"  segment #%u (name='%s', version='%s', offset='0x%lx', size='%u bytes')\\n\",\n\t\t\t\tsegNo + 1,\n\t\t\t\tpak->packageName,\n\t\t\t\tpak->packageVersion,\n\t\t\t\tmoff(epk, dataPtr),\n\t\t\t\tpak->segmentInfo.segmentSize\n\t\t\t);\n\n\t\t\tresult = wrap_decryptimage(\n\t\t\t\t(void *)dataPtr,\n\t\t\t\tpak->segmentInfo.segmentSize,\n\t\t\t\t(void *)dataPtr,\n\t\t\t\tconfig_opts->dest_dir,\n\t\t\t\tRAW,\n\t\t\t\tNULL\n\t\t\t);\n\n\t\t\tif(result < 0){\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif(epkType == EPK_V3_NEW){\n\t\t\t\tuint32_t decryptedSegmentIndex = *(uint32_t *)dataPtr;\n\t\t\t\tif(decryptedSegmentIndex != i){\n\t\t\t\t\tprintf(\"Warning: Decrypted segment doesn't match expected index! (index: %d, expected: %d)\\n\",\n\t\t\t\t\t\t\tdecryptedSegmentIndex, i\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tmwrite(dataPtr + 4, pak->segmentInfo.segmentSize, 1, pakFile);\n\t\t\t} else {\n\t\t\t\tmwrite(dataPtr, pak->segmentInfo.segmentSize, 1, pakFile);\n\t\t\t}\n\n\t\t\tdataPtr += pak->segmentInfo.segmentSize;\n\n\t\t\t/* for segment index in new EPK3 */\n\t\t\tdataPtr += extraSegmentSize;\n\t\t}\n\n\t\tmclose(pakFile);\n\t\thandle_file(pakFileName, config_opts);\n\t\tfree(pakFileName);\n\t}\n}\n\n"
  },
  {
    "path": "src/jffs2/CMakeLists.txt",
    "content": "add_library(jffs2 crc32.cpp jffs2extract.cpp mini_inflate.cpp)\ntarget_include_directories(jffs2 PUBLIC\n\t${INC}\n\t${LZO_INCLUDE_DIR}\n\t${INC}/jffs2\n)\ntarget_link_libraries(jffs2 util mfile lzma ${LZO_LIBRARIES})"
  },
  {
    "path": "src/jffs2/crc32.cpp",
    "content": "unsigned long crc32(unsigned long, const unsigned char *, unsigned int);\n\nstatic const unsigned long crc_table[256] = {\n\t0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,\n\t0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,\n\t0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,\n\t0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,\n\t0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,\n\t0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,\n\t0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,\n\t0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,\n\t0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,\n\t0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,\n\t0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,\n\t0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,\n\t0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,\n\t0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,\n\t0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,\n\t0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,\n\t0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,\n\t0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,\n\t0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,\n\t0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,\n\t0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,\n\t0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,\n\t0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,\n\t0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,\n\t0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,\n\t0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,\n\t0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,\n\t0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,\n\t0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,\n\t0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,\n\t0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,\n\t0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,\n\t0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,\n\t0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,\n\t0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,\n\t0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,\n\t0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,\n\t0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,\n\t0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,\n\t0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,\n\t0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,\n\t0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,\n\t0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,\n\t0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,\n\t0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,\n\t0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,\n\t0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,\n\t0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,\n\t0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,\n\t0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,\n\t0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,\n\t0x2d02ef8dL\n};\n\n#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);\n#define DO2(buf)  DO1(buf); DO1(buf);\n#define DO4(buf)  DO2(buf); DO2(buf);\n#define DO8(buf)  DO4(buf); DO4(buf);\n\nunsigned long crc32_no_comp(unsigned long crc, const unsigned char *buf, int len) {\n\twhile (len >= 8) {\n\t\tDO8(buf);\n\t\tlen -= 8;\n\t}\n\tif (len)\n\t\tdo {\n\t\t\tDO1(buf);\n\t\t} while (--len);\n\n\treturn crc;\n}\n"
  },
  {
    "path": "src/jffs2/jffs2extract.cpp",
    "content": "/*\n * a very simple jffs2 unpacker.\n * algorithm is memory intensive but has (almost) linear complexity.\n * at first, the jffs2 is unpacked and put into a map, inode data blocks\n * sorted by version number.\n * then the data blocks are \"replayed\" in correct order, and memcpy'ed\n * into a buffer.\n *\n * usage: jffs2_unpack <jffs2 file> <output directory> <endianess>\n * ...where endianess is 4321 for big endian or 1234 for little endian.\n *\n * SECURITY NOTE: as you need to run this program as root, you could\n * easily build a fake-jffs2 file with relative pathnames, thus overwriting\n * any file on the host system! BE AWARE OF THIS!\n * (this could be easily avoided by checking directory. however, i don't\n * want to give any false sense of security. this program was NOT designed\n * with security in mind, and i know that this is no excuse.)\n *\n * License: GPL (due to the used unpack algorithms)\n *\n *                          (C) 2006 Felix Domke <tmbinc@elitedvb.net>\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <dirent.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n\n#ifdef __APPLE__\n#    include <machine/endian.h>\n#else\n#    include <endian.h>\n#    include <sys/sysmacros.h>\n#endif\n\n#include <map>\n#include <string>\n#include <list>\n#include <vector>\n#include <set>\n\n#include \"mfile.h\"\n#include \"common.h\"\n#include \"lzo/lzo1x.h\"\n#include \"lzma.h\"\n#include \"util.h\"\n\n#include \"os_byteswap.h\"\n#include \"jffs2/mini_inflate.h\"\n#include \"jffs2/jffs2.h\"\n\n#define PAD_U32(x) ((x + 3) & ~3)\n#define PAD_X(x, y) ((x + (y - 1) & ~(y - 1)))\n\n#define RUBIN_REG_SIZE   16\n#define UPPER_BIT_RUBIN    (((long) 1)<<(RUBIN_REG_SIZE-1))\n#define LOWER_BITS_RUBIN   ((((long) 1)<<(RUBIN_REG_SIZE-1))-1)\n\nextern unsigned long crc32_no_comp(unsigned long crc, const unsigned char *buf, int len);\n\nstatic int swap_words = -1;\nstatic int verbose = 0;\nstatic bool guess_es = false;\nstatic bool keep_unlinked = true;\n\nstatic CLzmaEncHandle *p;\nstatic uint8_t propsEncoded[LZMA_PROPS_SIZE];\nstatic size_t propsSize = sizeof(propsEncoded);\n\nunsigned short fix16(unsigned short c) {\n\tif (swap_words)\n\t\treturn bswap_16(c);\n\telse\n\t\treturn c;\n}\n\nunsigned long fix32(unsigned long c) {\n\tif (swap_words)\n\t\treturn bswap_32(c);\n\telse\n\t\treturn c;\n}\n\ntypedef __u32 u32;\n\nvoid lzma_free_workspace(void)\n{\n\tLzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc);\n}\n\n\nint lzma_alloc_workspace(CLzmaEncProps *props)\n{\n\tif ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL)\n\t{\n\t\tPRINT_ERROR(\"Failed to allocate lzma deflate workspace\\n\");\n\t\treturn -ENOMEM;\n\t}\n\n\tif (LzmaEnc_SetProps(p, props) != SZ_OK)\n\t{\n\t\tlzma_free_workspace();\n\t\treturn -1;\n\t}\n\n\tif (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK)\n\t{\n\t\tlzma_free_workspace();\n\t\treturn -1;\n\t}\n\n        return 0;\n}\n\nvoid rubin_do_decompress(unsigned char *bits, unsigned char *in, unsigned char *page_out, __u32 destlen) {\n\tregister unsigned char *curr = page_out;\n\tunsigned char *end = page_out + destlen;\n\tregister unsigned long temp;\n\tregister unsigned long result;\n\tregister unsigned long p;\n\tregister unsigned long q;\n\tregister unsigned long rec_q;\n\tregister unsigned long bit;\n\tregister long i0;\n\tunsigned long i;\n\n\t/* init_pushpull */\n\ttemp = *(u32 *) in;\n\tbit = 16;\n\n\t/* init_rubin */\n\tq = 0;\n\tp = (long)(2 * UPPER_BIT_RUBIN);\n\n\t/* init_decode */\n\trec_q = (in[0] << 8) | in[1];\n\n\twhile (curr < end) {\n\t\t/* in byte */\n\n\t\tresult = 0;\n\t\tfor (i = 0; i < 8; i++) {\n\t\t\t/* decode */\n\n\t\t\twhile ((q & UPPER_BIT_RUBIN) || ((p + q) <= UPPER_BIT_RUBIN)) {\n\t\t\t\tq &= ~UPPER_BIT_RUBIN;\n\t\t\t\tq <<= 1;\n\t\t\t\tp <<= 1;\n\t\t\t\trec_q &= ~UPPER_BIT_RUBIN;\n\t\t\t\trec_q <<= 1;\n\t\t\t\trec_q |= (temp >> (bit++ ^ 7)) & 1;\n\t\t\t\tif (bit > 31) {\n\t\t\t\t\tbit = 0;\n\t\t\t\t\ttemp = *(u32 *) in;\n\t\t\t\t\tin += 4;\n\t\t\t\t}\n\t\t\t}\n\t\t\ti0 = (bits[i] * p) >> 8;\n\n\t\t\tif (i0 <= 0)\n\t\t\t\ti0 = 1;\n\t\t\t/* if it fails, it fails, we have our crc\n\t\t\t   if (i0 >= p) i0 = p - 1; */\n\n\t\t\tresult >>= 1;\n\t\t\tif (rec_q < q + i0) {\n\t\t\t\t/* result |= 0x00; */\n\t\t\t\tp = i0;\n\t\t\t} else {\n\t\t\t\tresult |= 0x80;\n\t\t\t\tp -= i0;\n\t\t\t\tq += i0;\n\t\t\t}\n\t\t}\n\t\t*(curr++) = result;\n\t}\n}\n\nvoid dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, unsigned long sourcelen, unsigned long dstlen) {\n\tunsigned char bits[8];\n\tint c;\n\n\tfor (c = 0; c < 8; c++)\n\t\tbits[c] = (256 - data_in[c]);\n\n\trubin_do_decompress(bits, data_in + 8, cpage_out, dstlen);\n}\n\nvoid rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, u32 srclen, u32 destlen) {\n\tint positions[256];\n\tint outpos;\n\tint pos;\n\tint i;\n\n\toutpos = pos = 0;\n\n\tfor (i = 0; i < 256; positions[i++] = 0) ;\n\n\twhile (outpos < destlen) {\n\t\tunsigned char value;\n\t\tint backoffs;\n\t\tint repeat;\n\n\t\tvalue = data_in[pos++];\n\t\tcpage_out[outpos++] = value;\t/* first the verbatim copied byte */\n\t\trepeat = data_in[pos++];\n\t\tbackoffs = positions[value];\n\n\t\tpositions[value] = outpos;\n\t\tif (repeat) {\n\t\t\tif (backoffs + repeat >= outpos) {\n\t\t\t\twhile (repeat) {\n\t\t\t\t\tcpage_out[outpos++] = cpage_out[backoffs++];\n\t\t\t\t\trepeat--;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (i = 0; i < repeat; i++)\n\t\t\t\t\t*(cpage_out + outpos + i) = *(cpage_out + backoffs + i);\n\t\t\t\toutpos += repeat;\n\t\t\t}\n\t\t}\n\t}\n}\n\nlong zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen) {\n\treturn (decompress_block(cpage_out, data_in + 2, memcpy));\n}\n\nlong lzma_decompress(unsigned char *data_in, unsigned char *cpage_out,\n\t\t\t\t uint32_t srclen, uint32_t destlen)\n{\n\tint ret;\n\tsize_t dl = (size_t)destlen;\n\tsize_t sl = (size_t)srclen;\n\tELzmaStatus status;\n\n\tret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded,\n\t\tpropsSize, LZMA_FINISH_ANY, &status, &lzma_alloc);\n\n\tif (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (size_t)destlen)\n\t\treturn -1;\n\n\treturn destlen;\n}\n\nlong lzo_decompress(unsigned char *data_in, unsigned char *cpage_out,\n\t\t\t\t uint32_t srclen, uint32_t destlen)\n{\n\tsize_t dl = destlen;\n\tint ret;\n\n\tret = lzo1x_decompress_safe(data_in, srclen, cpage_out, &dl, NULL);\n\n\tif (ret != LZO_E_OK || dl != destlen)\n\t\treturn -1;\n\n\treturn dl;\n}\n\n\nint do_uncompress(void *dst, int dstlen, void *src, int srclen, int type) {\n\tswitch (type) {\n\tcase JFFS2_COMPR_NONE:\n\t\tmemcpy(dst, src, dstlen);\n\t\treturn dstlen;\n\tcase JFFS2_COMPR_ZERO:\n\t\tmemset(dst, 0, dstlen);\n\t\treturn dstlen;\n\tcase JFFS2_COMPR_RTIME:\n\t\trtime_decompress((unsigned char *)src, (unsigned char *)dst, srclen, dstlen);\n\t\treturn dstlen;\n\tcase JFFS2_COMPR_RUBINMIPS:\n\t\tbreak;\n\tcase JFFS2_COMPR_COPY:\n\t\tbreak;\n\tcase JFFS2_COMPR_DYNRUBIN:\n\t\tdynrubin_decompress((unsigned char *)src, (unsigned char *)dst, srclen, dstlen);\n\t\treturn dstlen;\n\tcase JFFS2_COMPR_ZLIB:\n\t\treturn zlib_decompress((unsigned char *)src, (unsigned char *)dst, srclen, dstlen);\n\tcase JFFS2_COMPR_LZO:\n\t\treturn lzo_decompress((unsigned char *)src, (unsigned char *)dst, srclen, dstlen);\n\tcase JFFS2_COMPR_LZMA:\n\t\treturn lzma_decompress((unsigned char *)src, (unsigned char *)dst, srclen, dstlen);\n\t}\n\tprintf(\"  ** unknown compression type %d!\\n\", type);\n\treturn -1;\n}\n\nstd::map <int, std::string> inodes;\nstd::map <int, __u8> node_type;\nstd::map <int, std::list <int> > childs;\n\nstruct nodedata_s {\n\tunsigned char *data;\n\tint size;\n\tint offset;\n\n\tint isize, gid, uid, mode;\n\n\tnodedata_s(unsigned char *_data, int _size, int _offset, int _isize, int _gid, int _uid, int _mode) {\n\t\tdata = (unsigned char *)malloc(_size);\n\t\tsize = _size;\n\t\toffset = _offset;\n\t\tmemcpy(data, _data, size);\n\n\t\tisize = _isize;\n\t\tgid = _gid;\n\t\tuid = _uid;\n\t\tmode = _mode;\n\t} nodedata_s() {\n\t\tdata = 0;\n\t\tsize = 0;\n\t\toffset = 0;\n\n\t\tisize = 0;\n\t\tgid = 0;\n\t\tuid = 0;\n\t\tmode = 0;\n\t}\n};\n\nstd::map <int, std::map <int, struct nodedata_s>> nodedata;\n\nint whine = 0;\nstd::string prefix;\nFILE *devtab;\n\nvoid do_list(int inode, std::string root = \"\") {\n\tstd::string pathname = prefix + root + inodes[inode];\n\n\tstd::map <int, struct nodedata_s> &data = nodedata[inode];\n\n\t//printf(\"inode %d -> %s\\n\", inode, inodes[inode].c_str());\n\n\tint max_size = 0, gid = 0, uid = 0, mode = 0755;\n\tif (!data.empty()) {\n\t\tstd::map <int, struct nodedata_s>::iterator last = data.end();\n\t\t--last;\n\t\tmax_size = last->second.isize;\n\t\tmode = last->second.mode;\n\t\tgid = last->second.gid;\n\t\tuid = last->second.uid;\n\t}\n\n\tif ((node_type[inode] == DT_BLK) || (node_type[inode] == DT_CHR))\n\t\tmax_size = 2;\n\n\tunsigned char *merged_data = (unsigned char *)calloc(1, max_size + 1);\n\tint devtab_type = 0, major = 0, minor = 0;\n\n\tfor (auto i : data) {\n\t\tint size = i.second.size;\n\t\tint offset = i.second.offset;\n\t\tif (offset + size > max_size)\n\t\t\tsize = max_size - offset;\n\t\tif (size > 0)\n\t\t\tmemcpy(merged_data + i.second.offset, i.second.data, i.second.size);\n\t}\n\n\tswitch (node_type[inode]) {\n\tcase DT_DIR:\n\t\tif (mkdir(pathname.c_str(), mode & 0777)){\n\t\t\tfprintf(stderr, \"mkdir '%s' failed (%s)\\n\", pathname.c_str(), strerror(errno));\n\t\t}\n\t\tdevtab_type = 'd';\n\t\tbreak;\n\n\tcase DT_REG:\n\t\t{\n\t\t\tFILE *f = fopen(pathname.c_str(), \"wb\");\n\t\t\tif (!f){\n\t\t\t\tfprintf(stderr, \"fopen '%s' failed (%s)\\n\", pathname.c_str(), strerror(errno));\n\t\t\t} else {\n\t\t\t\tfwrite(merged_data, max_size, 1, f);\n\t\t\t\tfclose(f);\n\t\t\t}\n\t\t\tdevtab_type = 'f';\n\t\t\tbreak;\n\t\t}\n\tcase DT_LNK:\n\t\t{\n\t\t\tsymlink((char *)merged_data, pathname.c_str());\n\t\t\tbreak;\n\t\t}\n\tcase DT_CHR:\n\tcase DT_BLK:\n\t\t{\n\t\t\tmajor = merged_data[1];\n\t\t\tminor = merged_data[0];\n\t\t\tif (mknod(pathname.c_str(), ((node_type[inode] == DT_BLK) ? S_IFBLK : S_IFCHR) | (mode & 07777), makedev(major, minor))) {\n\t\t\t\tif (!whine++){\n\t\t\t\t\tfprintf(stderr, \"mknod '%s' failed (%s)\\n\", pathname.c_str(), strerror(errno));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (node_type[inode] == DT_BLK)\n\t\t\t\tdevtab_type = 'b';\n\t\t\telse\n\t\t\t\tdevtab_type = 'c';\n\t\t\tbreak;\n\t\t}\n\tcase DT_FIFO:\n\t\t{\n\t\t\tif (mkfifo(pathname.c_str(), mode) < 0)\n\t\t\t\tfprintf(stderr, \"failed to create FIFO(%s) (%s)\\n\", pathname.c_str(), strerror(errno));\n\t\t\tbreak;\n\t\t}\n\tcase DT_SOCK: {\n\t\t// create and close a TCP Unix Socket\n\t\tint sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);\n\t\tconst char *cpath = pathname.c_str();\n\n\t\tif(sock_fd < 0){\n\t\t\tfprintf(stderr, \"failed to create unix socket '%s' (%s)\\n\", cpath, strerror(errno));\n\t\t\tbreak;\n\t\t}\n\t\tclose(sock_fd);\n\t\tbreak;\n\t}\n\tcase DT_WHT:\n\t\tgoto node_warn_uhnandled;\n\tcase DT_UNKNOWN:\n\t\t//deletion node\n\t\tif(inode == 0){\n\t\t\tconst char *cpath = pathname.c_str();\n\n\t\t\tif(keep_unlinked){\n\t\t\t\tint nidx = 0;\n\t\t\t\tstd::string suffix = \"\";\n\n\t\t\t\twhile(access((pathname + suffix).c_str(), F_OK ) != -1){\n\t\t\t\t\tsuffix = std::to_string(nidx++);\n\t\t\t\t}\n\n\t\t\t\tstd::string new_name = pathname + suffix;\n\n\t\t\t\tMFILE *f_src = mopen(cpath, O_RDONLY);\n\t\t\t\tMFILE *f_dst = mfopen(new_name.c_str(), \"w+\");\n\t\t\t\tif(!f_src || !f_dst){\n\t\t\t\t\tfprintf(stderr, \"failed to copy '%s' to '%s'\\n\", cpath, new_name.c_str());\n\t\t\t\t\tif(f_src)\n\t\t\t\t\t\tmclose(f_src);\n\t\t\t\t\tif(f_dst)\n\t\t\t\t\t\tmclose(f_dst);\n\t\t\t\t} else {\n\t\t\t\t\tmfile_map(f_dst, msize(f_src));\n\t\t\t\t\tmemcpy(\n\t\t\t\t\t\tmdata(f_dst, void),\n\t\t\t\t\t\tmdata(f_src, void),\n\t\t\t\t\t\tmsize(f_src)\n\t\t\t\t\t);\n\t\t\t\t\tmclose(f_dst);\n\t\t\t\t\tmclose(f_src);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tnode_warn_uhnandled:\n\t\t\tprintf(\"warning:unhandled inode type(%d) for inode %d\\n\", node_type[inode], inode);\n\t\t}\n\t\tbreak;\n\t}\n\n\tfree(merged_data);\n\n\tif (devtab_type && devtab && (inode != 1)){\n\t\tfprintf(devtab, \"%s %c %o %d %d %d %d - - -\\n\",\n\t\t\t(root + inodes[inode]).c_str(),\n\t\t\tdevtab_type,\n\t\t\tmode & 07777,\n\t\t\tuid, gid, major, minor\n\t\t);\n\t}\n\n\tif (node_type[inode] != DT_LNK) {\n\t\tif (chmod(pathname.c_str(), mode))\n\t\t\tif (!whine++){\n\t\t\t\tfprintf(stderr, \"chmod failed for '%s' (%s)\\n\", pathname.c_str(), strerror(errno));\n\t\t\t}\n\n\t\tif (chown(pathname.c_str(), uid, gid)) {\n#ifndef __CYGWIN__\n\t\t\tif (!whine++)\n\t\t\t\tfprintf(stderr, \"chown failed for '%s' (%s)\\n\", pathname.c_str(), strerror(errno));\n#endif\n\t\t}\n\t}\n//  printf(\"%s (%d)\\n\", pathname.c_str(), max_size);\n\tstd::list < int >&child = childs[inode];\n\tfor (auto i : child)\n\t\tdo_list(i, root + inodes[inode].c_str() + \"/\");\n}\n\n\ninline int is_jffs2_magic(uint16_t val){\n\tif(val == KSAMTIB_CIGAM_2SFFJ){\n\t\tfputs(\"invalid endianess detected\\n\", stderr);\n\t\treturn -1;\n\t}\n\treturn (val == JFFS2_MAGIC_BITMASK);\n}\n\nsize_t contiguos_region_size(MFILE *mf, off_t offset, uint8_t match_pattern){\n\tuint8_t *pStart = mdata(mf, uint8_t);\n\tuint8_t *cursor = pStart + offset;\n\tsize_t fileSz = msize(mf);\n\n\tfor(; moff(mf, cursor) < fileSz; cursor++){\n\t\tif(*cursor != match_pattern)\n\t\t\tbreak;\n\t}\n\treturn (cursor - pStart) - offset;\n}\n\nuint32_t try_guess_es(MFILE *mf, bool *is_reliable){\n\tuint8_t *data = mdata(mf, uint8_t);\n\tsize_t fileSz = msize(mf);\n\n\t*is_reliable = false;\n\n\tuint8_t blk16[16];\n\tmemset(&blk16, 0xFF, sizeof(blk16));\n\n\t// find start of remaining data\n\toff_t off = 0;\n\tfor(; off < fileSz; off += sizeof(blk16)){\n\t\tif(!memcmp(data + off, &blk16, sizeof(blk16)))\n\t\t\tbreak;\n\t}\n\n\tif(off == fileSz)\n\t\treturn 0;\n\n\t// align to 16\n\tint remainder = off % 16;\n\twhile(remainder > 0){\n\t\tif(*(data + (off++)) != 0xFF)\n\t\t\treturn off;\n\t}\n\n\t// find end\n\tfor(; off < fileSz; off += sizeof(blk16)){\n\t\tif(memcmp(data + off, &blk16, sizeof(blk16)) != 0)\n\t\t\tbreak;\n\t}\n\n\t// align to next JFFS2 header\n\tfor(int i=0; i<=32; i++, off++){\n\t\tunion jffs2_node_union *hdr = (union jffs2_node_union *)(data + off);\n\t\tif((is_jffs2_magic(hdr->u.magic)) &&\n\t\t\tcrc32_no_comp(0, (uint8_t *)hdr, sizeof(hdr->u) - 4) == fix32(hdr->u.hdr_crc)\n\t\t){\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t*is_reliable = true;\n\treturn off;\n}\n\nunion jffs2_node_union *find_next_node(MFILE *mf, off_t cur_off, int erase_size){\n\tuint8_t *data = mdata(mf, uint8_t);\n\tsize_t fileSz = msize(mf);\n\n\t// find empty FS data\n\t{\n\t\tsize_t empty_fsdata_sz = contiguos_region_size(mf, cur_off, 0x0);\n\t\tif(empty_fsdata_sz != 0){\n\t\t\tif(verbose)\n\t\t\t\tprintf(\"region(0x00) = 0x%x\\n\", empty_fsdata_sz);\n\t\t}\n\n\t\tcur_off += empty_fsdata_sz;\n\t}\n\n\tif(erase_size > -1){\n\t\tcur_off = PAD_X(cur_off, erase_size);\n\t\tgoto find_jffs2;\n\t}\n\n\t// find empty eraseblocks\n\t{\n\t\tsize_t empty_esblks_sz = contiguos_region_size(mf, cur_off, 0xFF);\n\t\tif(empty_esblks_sz != 0){\n\t\t\tif(verbose)\n\t\t\t\tprintf(\"region(0xFF) = 0x%x\\n\", empty_esblks_sz);\n\t\t}\n\n\t\tcur_off += empty_esblks_sz;\n\t}\n\n\tfind_jffs2:\n\toff_t off;\n\tfor(off = cur_off; off < fileSz;){\n\t\tunion jffs2_node_union *node = (union jffs2_node_union *)(data + off);\n\t\tint r;\n\t\tif((r=is_jffs2_magic(node->u.magic)) &&\n\t\t\tcrc32_no_comp(0, (uint8_t *)node, sizeof(node->u) - 4) == fix32(node->u.hdr_crc)\n\t\t){\n\t\t\treturn node;\n\t\t}\n\n\t\t// if something unusual happened, stop search\n\t\tif(r < 0){\n\t\t\tbreak;\n\t\t}\n\n\t\tif(erase_size > -1){\n\t\t\toff += erase_size;\n\t\t} else {\n\t\t\toff += 4;\n\t\t}\n\t}\n\treturn NULL;\n}\n\nextern \"C\" int jffs2extract(char *infile, char *outdir, struct jffs2_main_args args) {\n\tint errors = 0;\n\n\tverbose = args.verbose;\n\tkeep_unlinked = args.keep_unlinked;\n\n\tMFILE *mf = mopen(infile, O_RDONLY);\n\tif (!mf) {\n\t\tfprintf(stderr, \"Failed to open '%s'\\n\", infile);\n\t\treturn 1;\n\t}\n\n\tunion jffs2_node_union *node = mdata(mf, union jffs2_node_union);\n\n\tswap_words = (node->u.magic == KSAMTIB_CIGAM_2SFFJ);\n\n\tbool es_reliable = false;\n\tuint32_t es;\n\tif(args.erase_size > -1){\n\t\tes = args.erase_size;\n\t} else if(guess_es){\n\t\tes = try_guess_es(mf, &es_reliable);\n\t\tprintf(\"> Guessed Erase Size: 0x%x (reliable=%d)\\n\", es, es_reliable);\n\t}\n\n\tuint8_t *data = mdata(mf, uint8_t);\n\n\toff_t off = moff(mf, node);\n\twhile(off + sizeof(*node) < msize(mf)){\n\t\tnode = (union jffs2_node_union *)&data[off];\n\t\tif(!is_jffs2_magic(node->u.magic) || node->u.totlen == 0){\n\t\t\tprintf(\"invalid node - scanning next node... (offset: %p)\\n\", off);\n\n\t\t\tint use_es = -1;\n\t\t\tif(es_reliable){\n\t\t\t\tuse_es = es;\n\t\t\t}\n\t\t\tnode = find_next_node(mf, off, use_es);\n\t\t\tif(node == NULL){\n\t\t\t\t// reached EOF\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\toff_t prev_off = off;\n\t\t\toff = moff(mf, node);\n\t\t\tprintf(\"found at %p, after 0x%x bytes\\n\", off, off - prev_off);\n\t\t}\n\t\tif(moff(mf, node) + sizeof(*node) >= msize(mf)){\n\t\t\tcontinue;\n\t\t}\n\n\t\toff += PAD_U32(node->u.totlen);\n\t\tif (verbose)\n\t\t\tprintf(\"at %08x: %04x | %04x (%lu bytes): \", off, fix16(node->u.magic), fix16(node->u.nodetype), fix32(node->u.totlen));\n\n\t\tif (crc32_no_comp(0, (unsigned char *)node, sizeof(node->u) - 4) != fix32(node->u.hdr_crc)) {\n\t\t\t++errors;\n\t\t\tprintf(\" ** wrong crc **\\n\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tswitch (fix16(node->u.nodetype)) {\n\t\t\tcase JFFS2_NODETYPE_DIRENT:\n\t\t\t{\n\t\t\t\tchar name[node->d.nsize + 1];\n\t\t\t\tstrncpy(name, (char *)node->d.name, node->d.nsize);\n\t\t\t\tname[node->d.nsize] = 0;\n\n\t\t\t\tif (verbose)\n\t\t\t\t\tprintf(\"DIRENT, ino %lu (%s), parent=%lu\\n\", fix32(node->d.ino), name, fix32(node->d.pino));\n\n\t\t\t\tuint32_t ino = fix32(node->d.ino);\n\t\t\t\tuint32_t pino = fix32(node->d.pino);\n\n\t\t\t\tinodes[ino] = name;\n\t\t\t\tnode_type[ino] = node->d.type;\n\t\t\t\tchilds[pino].push_back(ino);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase JFFS2_NODETYPE_INODE:\n\t\t\t{\n\t\t\t\tif (verbose)\n\t\t\t\t\tprintf(\"\\n\");\n\t\t\t\tif (crc32_no_comp(0, (unsigned char *)&(node->i), sizeof(struct jffs2_raw_inode) - 8) != fix32(node->i.node_crc)) {\n\t\t\t\t\terrors++;\n\t\t\t\t\tprintf(\"  ** wrong node crc **\\n\");\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (verbose) {\n\t\t\t\t\tprintf(\"  INODE, ino %lu (version %lu) at %08lx\\n\", fix32(node->i.ino), fix32(node->i.version), fix32(node->i.offset));\n\t\t\t\t\tprintf(\"  compression: %d, user compression requested: %d\\n\", node->i.compr, node->i.usercompr);\n\t\t\t\t}\n\t\t\t\tint compr_size = fix32(node->i.csize);\n\t\t\t\tint uncompr_size = fix32(node->i.dsize);\n\t\t\t\tif (verbose)\n\t\t\t\t\tprintf(\"  compr_size: %d, uncompr_size: %d\\n\", compr_size, uncompr_size);\n\n\t\t\t\tuint8_t *compr = node->i.data;\n\t\t\t\tuint8_t uncomp[uncompr_size];\n\n\t\t\t\tint extracted_size;\n\t\t\t\tif (crc32_no_comp(0, compr, compr_size) != fix32(node->i.data_crc)) {\n\t\t\t\t\terrors++;\n\t\t\t\t\tprintf(\"  ** wrong data crc **\\n\");\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\tif (verbose)\n\t\t\t\t\t\tprintf(\"  data crc ok\\n\");\n\t\t\t\t\tif ((extracted_size=do_uncompress(uncomp, uncompr_size, compr, compr_size, node->i.compr)) != uncompr_size) {\n\t\t\t\t\t\terrors++;\n\t\t\t\t\t\tprintf(\"  ** data uncompress failed! (%u =! %u)\\n\", extracted_size, uncompr_size);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnodedata[fix32(node->i.ino)][fix32(node->i.version)] = nodedata_s(\n\t\t\t\t\t\t\tuncomp, uncompr_size, fix32(node->i.offset),\n\t\t\t\t\t\t\tfix32(node->i.isize), fix32(node->i.gid),\n\t\t\t\t\t\t\tfix32(node->i.uid), fix32(node->i.mode)\n\t\t\t\t\t\t);\n#if 0\n\t\t\t\t\t\tint i;\n\t\t\t\t\t\tfor (i = 0; i < ((uncompr_size + 15) & ~15); ++i) {\n\t\t\t\t\t\t\tif ((i & 15) == 0)\n\t\t\t\t\t\t\t\tprintf(\"%08x: \", fix32(node.i.offset) + i);\n\t\t\t\t\t\t\tif (i < uncompr_size)\n\t\t\t\t\t\t\t\tprintf(\"%02x \", uncomp[i]);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tprintf(\"   \");\n\t\t\t\t\t\t\tif ((i & 15) == 15)\n\t\t\t\t\t\t\t\tprintf(\"\\n\");\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase JFFS2_NODETYPE_CLEANMARKER:\n\t\t\t\tif (verbose)\n\t\t\t\t\tprintf(\"CLEANMARKER\\n\");\n\t\t\t\tbreak;\n\t\t\tcase JFFS2_NODETYPE_PADDING:\n\t\t\t\tif (verbose)\n\t\t\t\t\tprintf(\"PADDING\\n\");\n\t\t\t\tbreak;\n\t\t\tcase JFFS2_NODETYPE_SUMMARY:\n\t\t\t\tif (verbose)\n\t\t\t\t\tprintf(\"SUMMARY\\n\");\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\terrors++;\n\t\t\t\tprintf(\" ** INVALID ** - nodetype %04x (offset: %p)\\n\", fix16(node->u.nodetype), off);\n\t\t}\n\t}\n\n\tif (errors) {\n\t\tif (!inodes.empty())\n\t\t\tprintf(\"there were errors, but some valid stuff was detected. continuing.\\n\");\n\t\telse {\n\t\t\tfprintf(stderr, \"errors present and no valid data.\\n\");\n\t\t\tmclose(mf);\n\t\t\treturn 2;\n\t\t}\n\t}\n\n\tnode_type[1] = DT_DIR;\n\tprefix = outdir;\n\tdevtab = fopen((prefix + \".devtab\").c_str(), \"wb\");\n\tdo_list(1);\n\tfclose(devtab);\n\n\tmclose(mf);\n\treturn 0;\n}\n"
  },
  {
    "path": "src/jffs2/mini_inflate.cpp",
    "content": "/*-------------------------------------------------------------------------\n * Filename:      mini_inflate.c\n * Version:       $Id: mini_inflate.c,v 1.3 2002/01/24 22:58:42 rfeany Exp $\n * Copyright:     Copyright (C) 2001, Russ Dill\n * Author:        Russ Dill <Russ.Dill@asu.edu>\n * Description:   Mini inflate implementation (RFC 1951)\n *-----------------------------------------------------------------------*/\n/*\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n */\n\n#include <mini_inflate.h>\n\n/* The order that the code lengths in section 3.2.7 are in */\nstatic unsigned char huffman_order[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5,\n\t11, 4, 12, 3, 13, 2, 14, 1, 15\n};\n\ninline void cramfs_memset(int *s, const int c, size n) {\n\tn--;\n\tfor (; n > 0; n--)\n\t\ts[n] = c;\n\ts[0] = c;\n}\n\n/* associate a stream with a block of data and reset the stream */\nstatic void init_stream(struct bitstream *stream, unsigned char *data, void *(*inflate_memcpy) (void *, const void *, size)) {\n\tstream->error = NO_ERROR;\n\tstream->memcpy = inflate_memcpy;\n\tstream->decoded = 0;\n\tstream->data = data;\n\tstream->bit = 0;\t\t\t/* The first bit of the stream is the lsb of the\n\t\t\t\t\t\t\t\t * first byte */\n\n\t/* really sorry about all this initialization, think of a better way,\n\t * let me know and it will get cleaned up */\n\tstream->codes.bits = 8;\n\tstream->codes.num_symbols = 19;\n\tstream->codes.lengths = stream->code_lengths;\n\tstream->codes.symbols = stream->code_symbols;\n\tstream->codes.count = stream->code_count;\n\tstream->codes.first = stream->code_first;\n\tstream->codes.pos = stream->code_pos;\n\n\tstream->lengths.bits = 16;\n\tstream->lengths.num_symbols = 288;\n\tstream->lengths.lengths = stream->length_lengths;\n\tstream->lengths.symbols = stream->length_symbols;\n\tstream->lengths.count = stream->length_count;\n\tstream->lengths.first = stream->length_first;\n\tstream->lengths.pos = stream->length_pos;\n\n\tstream->distance.bits = 16;\n\tstream->distance.num_symbols = 32;\n\tstream->distance.lengths = stream->distance_lengths;\n\tstream->distance.symbols = stream->distance_symbols;\n\tstream->distance.count = stream->distance_count;\n\tstream->distance.first = stream->distance_first;\n\tstream->distance.pos = stream->distance_pos;\n\n}\n\n/* pull 'bits' bits out of the stream. The last bit pulled it returned as the\n * msb. (section 3.1.1)\n */\ninline unsigned long pull_bits(struct bitstream *stream, const unsigned int bits) {\n\tunsigned long ret;\n\tunsigned int i;\n\n\tret = 0;\n\tfor (i = 0; i < bits; i++) {\n\t\tret += ((*(stream->data) >> stream->bit) & 1) << i;\n\n\t\t/* if, before incrementing, we are on bit 7,\n\t\t * go to the lsb of the next byte */\n\t\tif (stream->bit++ == 7) {\n\t\t\tstream->bit = 0;\n\t\t\tstream->data++;\n\t\t}\n\t}\n\treturn ret;\n}\n\ninline int pull_bit(struct bitstream *stream) {\n\tint ret = ((*(stream->data) >> stream->bit) & 1);\n\tif (stream->bit++ == 7) {\n\t\tstream->bit = 0;\n\t\tstream->data++;\n\t}\n\treturn ret;\n}\n\n/* discard bits up to the next whole byte */\nstatic void discard_bits(struct bitstream *stream) {\n\tif (stream->bit != 0) {\n\t\tstream->bit = 0;\n\t\tstream->data++;\n\t}\n}\n\n/* No decompression, the data is all literals (section 3.2.4) */\nstatic void decompress_none(struct bitstream *stream, unsigned char *dest) {\n\tunsigned int length;\n\n\tdiscard_bits(stream);\n\tlength = *(stream->data++);\n\tlength += *(stream->data++) << 8;\n\tpull_bits(stream, 16);\t\t/* throw away the inverse of the size */\n\n\tstream->decoded += length;\n\tstream->memcpy(dest, stream->data, length);\n\tstream->data += length;\n}\n\n/* Read in a symbol from the stream (section 3.2.2) */\nstatic int read_symbol(struct bitstream *stream, struct huffman_set *set) {\n\tint bits = 0;\n\tint code = 0;\n\twhile (!(set->count[bits] && code < set->first[bits] + set->count[bits])) {\n\t\tcode = (code << 1) + pull_bit(stream);\n\t\tif (++bits > set->bits) {\n\t\t\t/* error decoding (corrupted data?) */\n\t\t\tstream->error = CODE_NOT_FOUND;\n\t\t\treturn -1;\n\t\t}\n\t}\n\treturn set->symbols[set->pos[bits] + code - set->first[bits]];\n}\n\n/* decompress a stream of data encoded with the passed length and distance\n * huffman codes */\nstatic void decompress_huffman(struct bitstream *stream, unsigned char *dest) {\n\tstruct huffman_set *lengths = &(stream->lengths);\n\tstruct huffman_set *distance = &(stream->distance);\n\n\tint symbol, length, dist, i;\n\n\tdo {\n\t\tif ((symbol = read_symbol(stream, lengths)) < 0)\n\t\t\treturn;\n\t\tif (symbol < 256) {\n\t\t\t*(dest++) = symbol;\t/* symbol is a literal */\n\t\t\tstream->decoded++;\n\t\t} else if (symbol > 256) {\n\t\t\t/* Determine the length of the repitition\n\t\t\t * (section 3.2.5) */\n\t\t\tif (symbol < 265)\n\t\t\t\tlength = symbol - 254;\n\t\t\telse if (symbol == 285)\n\t\t\t\tlength = 258;\n\t\t\telse {\n\t\t\t\tlength = pull_bits(stream, (symbol - 261) >> 2);\n\t\t\t\tlength += (4 << ((symbol - 261) >> 2)) + 3;\n\t\t\t\tlength += ((symbol - 1) % 4) << ((symbol - 261) >> 2);\n\t\t\t}\n\n\t\t\t/* Determine how far back to go */\n\t\t\tif ((symbol = read_symbol(stream, distance)) < 0)\n\t\t\t\treturn;\n\t\t\tif (symbol < 4)\n\t\t\t\tdist = symbol + 1;\n\t\t\telse {\n\t\t\t\tdist = pull_bits(stream, (symbol - 2) >> 1);\n\t\t\t\tdist += (2 << ((symbol - 2) >> 1)) + 1;\n\t\t\t\tdist += (symbol % 2) << ((symbol - 2) >> 1);\n\t\t\t}\n\t\t\tstream->decoded += length;\n\t\t\tfor (i = 0; i < length; i++) {\n\t\t\t\t*dest = dest[-dist];\n\t\t\t\tdest++;\n\t\t\t}\n\t\t}\n\t} while (symbol != 256);\t/* 256 is the end of the data block */\n}\n\n/* Fill the lookup tables (section 3.2.2) */\nstatic void fill_code_tables(struct huffman_set *set) {\n\tint code = 0, i, length;\n\n\t/* fill in the first code of each bit length, and the pos pointer */\n\tset->pos[0] = 0;\n\tfor (i = 1; i < set->bits; i++) {\n\t\tcode = (code + set->count[i - 1]) << 1;\n\t\tset->first[i] = code;\n\t\tset->pos[i] = set->pos[i - 1] + set->count[i - 1];\n\t}\n\n\t/* Fill in the table of symbols in order of their huffman code */\n\tfor (i = 0; i < set->num_symbols; i++) {\n\t\tif ((length = set->lengths[i]))\n\t\t\tset->symbols[set->pos[length]++] = i;\n\t}\n\n\t/* reset the pos pointer */\n\tfor (i = 1; i < set->bits; i++)\n\t\tset->pos[i] -= set->count[i];\n}\n\nstatic void init_code_tables(struct huffman_set *set) {\n\tcramfs_memset(set->lengths, 0, set->num_symbols);\n\tcramfs_memset(set->count, 0, set->bits);\n\tcramfs_memset(set->first, 0, set->bits);\n}\n\n/* read in the huffman codes for dynamic decoding (section 3.2.7) */\nstatic void decompress_dynamic(struct bitstream *stream, unsigned char *dest) {\n\t/* I tried my best to minimize the memory footprint here, while still\n\t * keeping up performance. I really dislike the _lengths[] tables, but\n\t * I see no way of eliminating them without a sizable performance\n\t * impact. The first struct table keeps track of stats on each bit\n\t * length. The _length table keeps a record of the bit length of each\n\t * symbol. The _symbols table is for looking up symbols by the huffman\n\t * code (the pos element points to the first place in the symbol table\n\t * where that bit length occurs). I also hate the initization of these\n\t * structs, if someone knows how to compact these, lemme know. */\n\n\tstruct huffman_set *codes = &(stream->codes);\n\tstruct huffman_set *lengths = &(stream->lengths);\n\tstruct huffman_set *distance = &(stream->distance);\n\n\tint hlit = pull_bits(stream, 5) + 257;\n\tint hdist = pull_bits(stream, 5) + 1;\n\tint hclen = pull_bits(stream, 4) + 4;\n\tint length, curr_code, symbol, i, last_code;\n\n\tlast_code = 0;\n\n\tinit_code_tables(codes);\n\tinit_code_tables(lengths);\n\tinit_code_tables(distance);\n\n\t/* fill in the count of each bit length' as well as the lengths\n\t * table */\n\tfor (i = 0; i < hclen; i++) {\n\t\tlength = pull_bits(stream, 3);\n\t\tcodes->lengths[huffman_order[i]] = length;\n\t\tif (length)\n\t\t\tcodes->count[length]++;\n\n\t}\n\tfill_code_tables(codes);\n\n\t/* Do the same for the length codes, being carefull of wrap through\n\t * to the distance table */\n\tcurr_code = 0;\n\twhile (curr_code < hlit) {\n\t\tif ((symbol = read_symbol(stream, codes)) < 0)\n\t\t\treturn;\n\t\tif (symbol == 0) {\n\t\t\tcurr_code++;\n\t\t\tlast_code = 0;\n\t\t} else if (symbol < 16) {\t/* Literal length */\n\t\t\tlengths->lengths[curr_code] = last_code = symbol;\n\t\t\tlengths->count[symbol]++;\n\t\t\tcurr_code++;\n\t\t} else if (symbol == 16) {\t/* repeat the last symbol 3 - 6\n\t\t\t\t\t\t\t\t\t * times */\n\t\t\tlength = 3 + pull_bits(stream, 2);\n\t\t\tfor (; length; length--, curr_code++)\n\t\t\t\tif (curr_code < hlit) {\n\t\t\t\t\tlengths->lengths[curr_code] = last_code;\n\t\t\t\t\tlengths->count[last_code]++;\n\t\t\t\t} else {\t\t/* wrap to the distance table */\n\t\t\t\t\tdistance->lengths[curr_code - hlit] = last_code;\n\t\t\t\t\tdistance->count[last_code]++;\n\t\t\t\t}\n\t\t} else if (symbol == 17) {\t/* repeat a bit length 0 */\n\t\t\tcurr_code += 3 + pull_bits(stream, 3);\n\t\t\tlast_code = 0;\n\t\t} else {\t\t\t\t/* same, but more times */\n\t\t\tcurr_code += 11 + pull_bits(stream, 7);\n\t\t\tlast_code = 0;\n\t\t}\n\t}\n\tfill_code_tables(lengths);\n\n\t/* Fill the distance table, don't need to worry about wrapthrough\n\t * here */\n\tcurr_code -= hlit;\n\twhile (curr_code < hdist) {\n\t\tif ((symbol = read_symbol(stream, codes)) < 0)\n\t\t\treturn;\n\t\tif (symbol == 0) {\n\t\t\tcurr_code++;\n\t\t\tlast_code = 0;\n\t\t} else if (symbol < 16) {\n\t\t\tdistance->lengths[curr_code] = last_code = symbol;\n\t\t\tdistance->count[symbol]++;\n\t\t\tcurr_code++;\n\t\t} else if (symbol == 16) {\n\t\t\tlength = 3 + pull_bits(stream, 2);\n\t\t\tfor (; length; length--, curr_code++) {\n\t\t\t\tdistance->lengths[curr_code] = last_code;\n\t\t\t\tdistance->count[last_code]++;\n\t\t\t}\n\t\t} else if (symbol == 17) {\n\t\t\tcurr_code += 3 + pull_bits(stream, 3);\n\t\t\tlast_code = 0;\n\t\t} else {\n\t\t\tcurr_code += 11 + pull_bits(stream, 7);\n\t\t\tlast_code = 0;\n\t\t}\n\t}\n\tfill_code_tables(distance);\n\n\tdecompress_huffman(stream, dest);\n}\n\n/* fill in the length and distance huffman codes for fixed encoding\n * (section 3.2.6) */\nstatic void decompress_fixed(struct bitstream *stream, unsigned char *dest) {\n\t/* let gcc fill in the initial values */\n\tstruct huffman_set *lengths = &(stream->lengths);\n\tstruct huffman_set *distance = &(stream->distance);\n\n\tcramfs_memset(lengths->count, 0, 16);\n\tcramfs_memset(lengths->first, 0, 16);\n\tcramfs_memset(lengths->lengths, 8, 144);\n\tcramfs_memset(lengths->lengths + 144, 9, 112);\n\tcramfs_memset(lengths->lengths + 256, 7, 24);\n\tcramfs_memset(lengths->lengths + 280, 8, 8);\n\tlengths->count[7] = 24;\n\tlengths->count[8] = 152;\n\tlengths->count[9] = 112;\n\n\tcramfs_memset(distance->count, 0, 16);\n\tcramfs_memset(distance->first, 0, 16);\n\tcramfs_memset(distance->lengths, 5, 32);\n\tdistance->count[5] = 32;\n\n\tfill_code_tables(lengths);\n\tfill_code_tables(distance);\n\n\tdecompress_huffman(stream, dest);\n}\n\n/* returns the number of bytes decoded, < 0 if there was an error. Note that\n * this function assumes that the block starts on a byte boundry\n * (non-compliant, but I don't see where this would happen). section 3.2.3 */\nlong decompress_block(unsigned char *dest, unsigned char *source, void *(*inflate_memcpy) (void *, const void *, size)) {\n\tint bfinal, btype;\n\tstruct bitstream stream;\n\n\tinit_stream(&stream, source, inflate_memcpy);\n\tdo {\n\t\tbfinal = pull_bit(&stream);\n\t\tbtype = pull_bits(&stream, 2);\n\t\tif (btype == NO_COMP)\n\t\t\tdecompress_none(&stream, dest + stream.decoded);\n\t\telse if (btype == DYNAMIC_COMP)\n\t\t\tdecompress_dynamic(&stream, dest + stream.decoded);\n\t\telse if (btype == FIXED_COMP)\n\t\t\tdecompress_fixed(&stream, dest + stream.decoded);\n\t\telse\n\t\t\tstream.error = COMP_UNKNOWN;\n\t} while (!bfinal && !stream.error);\n\n#if 0\n\tputstr(\"decompress_block start\\r\\n\");\n\tputLabeledWord(\"stream.error = \", stream.error);\n\tputLabeledWord(\"stream.decoded = \", stream.decoded);\n\tputLabeledWord(\"dest = \", dest);\n\tputstr(\"decompress_block end\\r\\n\");\n#endif\n\treturn stream.error ? -stream.error : stream.decoded;\n}\n"
  },
  {
    "path": "src/lz4/CMakeLists.txt",
    "content": "add_library(lz4 lz4.c lz4hc.c lz4demo.c)\ntarget_include_directories(lz4 PUBLIC ${INC}/lz4)"
  },
  {
    "path": "src/lz4/bench.c",
    "content": "/*\n    bench.c - Demo program to benchmark open-source compression algorithm\n    Copyright (C) Yann Collet 2012\n\tGPL v2 License\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (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    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n\tYou can contact the author at :\n\t- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\n\t- LZ4 source repository : http://code.google.com/p/lz4/\n*/\n\n//**************************************\n// Compiler Options\n//**************************************\n// Visual warning messages\n#define _CRT_SECURE_NO_WARNINGS\n\n// Under Linux at least, pull in the *64 commands\n#define _LARGEFILE64_SOURCE\n\n// MSVC does not support S_ISREG\n#ifndef S_ISREG\n#    define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)\n#endif\n\n// GCC does not support _rotl outside of Windows\n#if !defined(_WIN32)\n#    define _rotl(x,r) ((x << r) | (x >> (32 - r)))\n#endif\n\n//**************************************\n// Includes\n//**************************************\n#include <stdlib.h>\t\t\t\t// malloc\n#include <stdio.h>\t\t\t\t// fprintf, fopen, ftello64\n#include <sys/timeb.h>\t\t\t// timeb\n#include <sys/types.h>\t\t\t// stat64\n#include <sys/stat.h>\t\t\t// stat64\n\n#include \"lz4.h\"\n#define COMPRESSOR0 LZ4_compress\n#include \"lz4hc.h\"\n#define COMPRESSOR1 LZ4_compressHC\n#define DEFAULTCOMPRESSOR LZ4_compress\n\n//**************************************\n// Basic Types\n//**************************************\n#if defined(_MSC_VER)\t\t\t// Visual Studio does not support 'stdint' natively\n#    define BYTE\tunsigned __int8\n#    define U16\t\tunsigned __int16\n#    define U32\t\tunsigned __int32\n#    define S32\t\t__int32\n#    define U64\t\tunsigned __int64\n#else\n#    include <stdint.h>\n#    define BYTE\tuint8_t\n#    define U16\t\tuint16_t\n#    define U32\t\tuint32_t\n#    define S32\t\tint32_t\n#    define U64\t\tuint64_t\n#endif\n\n//**************************************\n// Constants\n//**************************************\n#define NBLOOPS\t\t3\n#define TIMELOOP\t2000\n\n#define KNUTH\t\t2654435761U\n#define MAX_MEM\t\t(1984<<20)\n#define DEFAULT_CHUNKSIZE   (8<<20)\n\n//**************************************\n// Local structures\n//**************************************\nstruct chunkParameters {\n\tU32 id;\n\tchar *inputBuffer;\n\tchar *outputBuffer;\n\tint inputSize;\n\tint outputSize;\n};\n\nstruct compressionParameters {\n\tint (*compressionFunction) (const char *, char *, int);\n\tint (*decompressionFunction) (const char *, char *, int);\n};\n\n//**************************************\n// MACRO\n//**************************************\n#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)\n\n//**************************************\n// Benchmark Parameters\n//**************************************\nstatic int chunkSize = DEFAULT_CHUNKSIZE;\nstatic int nbIterations = NBLOOPS;\n\nvoid BMK_SetBlocksize(int bsize) {\n\tchunkSize = bsize;\n\tDISPLAY(\"-Using Block Size of %i KB-\", chunkSize >> 10);\n}\n\nvoid BMK_SetNbIterations(int nbLoops) {\n\tnbIterations = nbLoops;\n\tDISPLAY(\"- %i iterations-\", nbIterations);\n}\n\n//*********************************************************\n//  Private functions\n//*********************************************************\n\nstatic int BMK_GetMilliStart() {\n\t// Supposed to be portable\n\t// Rolls over every ~ 12.1 days (0x100000/24/60/60)\n\t// Use GetMilliSpan to correct for rollover\n\tstruct timeb tb;\n\tint nCount;\n\tftime(&tb);\n\tnCount = tb.millitm + (tb.time & 0xfffff) * 1000;\n\treturn nCount;\n}\n\nstatic int BMK_GetMilliSpan(int nTimeStart) {\n\tint nSpan = BMK_GetMilliStart() - nTimeStart;\n\tif (nSpan < 0)\n\t\tnSpan += 0x100000 * 1000;\n\treturn nSpan;\n}\n\nstatic U32 BMK_checksum_MMH3A(char *buff, U32 length) {\n\tconst BYTE *data = (const BYTE *)buff;\n\tconst int nblocks = length >> 2;\n\n\tU32 h1 = KNUTH;\n\tU32 c1 = 0xcc9e2d51;\n\tU32 c2 = 0x1b873593;\n\n\tconst U32 *blocks = (const U32 *)(data + nblocks * 4);\n\tint i;\n\n\tfor (i = -nblocks; i; i++) {\n\t\tU32 k1 = blocks[i];\n\n\t\tk1 *= c1;\n\t\tk1 = _rotl(k1, 15);\n\t\tk1 *= c2;\n\n\t\th1 ^= k1;\n\t\th1 = _rotl(h1, 13);\n\t\th1 = h1 * 5 + 0xe6546b64;\n\t}\n\n\t{\n\t\tconst BYTE *tail = (const BYTE *)(data + nblocks * 4);\n\t\tU32 k1 = 0;\n\n\t\tswitch (length & 3) {\n\t\tcase 3:\n\t\t\tk1 ^= tail[2] << 16;\n\t\tcase 2:\n\t\t\tk1 ^= tail[1] << 8;\n\t\tcase 1:\n\t\t\tk1 ^= tail[0];\n\t\t\tk1 *= c1;\n\t\t\tk1 = _rotl(k1, 15);\n\t\t\tk1 *= c2;\n\t\t\th1 ^= k1;\n\t\t};\n\t}\n\n\th1 ^= length;\n\th1 ^= h1 >> 16;\n\th1 *= 0x85ebca6b;\n\th1 ^= h1 >> 13;\n\th1 *= 0xc2b2ae35;\n\th1 ^= h1 >> 16;\n\n\treturn h1;\n}\n\nstatic size_t BMK_findMaxMem(U64 requiredMem) {\n\tsize_t step = (64U << 20);\t// 64 MB\n\tBYTE *testmem = NULL;\n\n\trequiredMem = (((requiredMem >> 25) + 1) << 26);\n\tif (requiredMem > MAX_MEM)\n\t\trequiredMem = MAX_MEM;\n\n\trequiredMem += 2 * step;\n\twhile (!testmem) {\n\t\trequiredMem -= step;\n\t\ttestmem = malloc((size_t) requiredMem);\n\t}\n\n\tfree(testmem);\n\treturn (size_t) (requiredMem - step);\n}\n\nstatic U64 BMK_GetFileSize(char *infilename) {\n\tint r;\n#if defined(_MSC_VER)\n\tstruct _stat64 statbuf;\n\tr = _stat64(infilename, &statbuf);\n#else\n\tstruct stat statbuf;\n\tr = stat(infilename, &statbuf);\n#endif\n\tif (r || !S_ISREG(statbuf.st_mode))\n\t\treturn 0;\t\t\t\t// No good...\n\treturn (U64) statbuf.st_size;\n}\n\n//*********************************************************\n//  Public function\n//*********************************************************\n\nint BMK_benchFile(char **fileNamesTable, int nbFiles, int cLevel) {\n\tint fileIdx = 0;\n\tFILE *fileIn;\n\tchar *infilename;\n\tU64 largefilesize;\n\tsize_t benchedsize;\n\tint nbChunks;\n\tint maxCChunkSize;\n\tsize_t readSize;\n\tchar *in_buff;\n\tchar *out_buff;\n\tint out_buff_size;\n\tstruct chunkParameters *chunkP;\n\tU32 crcc, crcd = 0;\n\tstruct compressionParameters compP;\n\n\tU64 totals = 0;\n\tU64 totalz = 0;\n\tdouble totalc = 0.;\n\tdouble totald = 0.;\n\n\t// Init\n\tswitch (cLevel) {\n#ifdef COMPRESSOR0\n\tcase 0:\n\t\tcompP.compressionFunction = COMPRESSOR0;\n\t\tbreak;\n#endif\n#ifdef COMPRESSOR1\n\tcase 1:\n\t\tcompP.compressionFunction = COMPRESSOR1;\n\t\tbreak;\n#endif\n\tdefault:\n\t\tcompP.compressionFunction = DEFAULTCOMPRESSOR;\n\t}\n\tcompP.decompressionFunction = LZ4_uncompress;\n\n\t// Loop for each file\n\twhile (fileIdx < nbFiles) {\n\t\t// Check file existence\n\t\tinfilename = fileNamesTable[fileIdx++];\n\t\tfileIn = fopen(infilename, \"rb\");\n\t\tif (fileIn == NULL) {\n\t\t\tDISPLAY(\"Pb opening %s\\n\", infilename);\n\t\t\treturn 11;\n\t\t}\n\t\t// Memory allocation & restrictions\n\t\tlargefilesize = BMK_GetFileSize(infilename);\n\t\tbenchedsize = (size_t) BMK_findMaxMem(largefilesize) / 2;\n\t\tif ((U64) benchedsize > largefilesize)\n\t\t\tbenchedsize = (size_t) largefilesize;\n\t\tif (benchedsize < largefilesize) {\n\t\t\tDISPLAY(\"Not enough memory for '%s' full size; testing %i MB only...\\n\", infilename, (int)(benchedsize >> 20));\n\t\t}\n\t\t// Alloc\n\t\tchunkP = (struct chunkParameters *)malloc(((benchedsize / chunkSize) + 1) * sizeof(struct chunkParameters));\n\t\tin_buff = malloc((size_t) benchedsize);\n\t\tnbChunks = (benchedsize / chunkSize) + 1;\n\t\tmaxCChunkSize = LZ4_compressBound(chunkSize);\n\t\tout_buff_size = nbChunks * maxCChunkSize;\n\t\tout_buff = malloc((size_t) out_buff_size);\n\n\t\tif (!in_buff || !out_buff) {\n\t\t\tDISPLAY(\"\\nError: not enough memory!\\n\");\n\t\t\tfree(in_buff);\n\t\t\tfree(out_buff);\n\t\t\tfclose(fileIn);\n\t\t\treturn 12;\n\t\t}\n\t\t// Init chunks data\n\t\t{\n\t\t\tint i;\n\t\t\tsize_t remaining = benchedsize;\n\t\t\tchar *in = in_buff;\n\t\t\tchar *out = out_buff;\n\t\t\tfor (i = 0; i < nbChunks; i++) {\n\t\t\t\tchunkP[i].id = i;\n\t\t\t\tchunkP[i].inputBuffer = in;\n\t\t\t\tin += chunkSize;\n\t\t\t\tif ((int)remaining > chunkSize) {\n\t\t\t\t\tchunkP[i].inputSize = chunkSize;\n\t\t\t\t\tremaining -= chunkSize;\n\t\t\t\t} else {\n\t\t\t\t\tchunkP[i].inputSize = remaining;\n\t\t\t\t\tremaining = 0;\n\t\t\t\t}\n\t\t\t\tchunkP[i].outputBuffer = out;\n\t\t\t\tout += maxCChunkSize;\n\t\t\t\tchunkP[i].outputSize = 0;\n\t\t\t}\n\t\t}\n\n\t\t// Fill input buffer\n\t\tDISPLAY(\"Loading %s...       \\r\", infilename);\n\t\treadSize = fread(in_buff, 1, benchedsize, fileIn);\n\t\tfclose(fileIn);\n\n\t\tif (readSize != benchedsize) {\n\t\t\tDISPLAY(\"\\nError: problem reading file '%s' !!    \\n\", infilename);\n\t\t\tfree(in_buff);\n\t\t\tfree(out_buff);\n\t\t\treturn 13;\n\t\t}\n\t\t// Calculating input Checksum\n\t\tcrcc = BMK_checksum_MMH3A(in_buff, benchedsize);\n\n\t\t// Bench\n\t\t{\n\t\t\tint loopNb, nb_loops, chunkNb;\n\t\t\tsize_t cSize = 0;\n\t\t\tint milliTime;\n\t\t\tdouble fastestC = 100000000., fastestD = 100000000.;\n\t\t\tdouble ratio = 0.;\n\n\t\t\tDISPLAY(\"\\r%79s\\r\", \"\");\n\t\t\tfor (loopNb = 1; loopNb <= nbIterations; loopNb++) {\n\t\t\t\t// Compression\n\t\t\t\tDISPLAY(\"%1i-%-14.14s : %9i ->\\r\", loopNb, infilename, (int)benchedsize);\n\t\t\t\t{\n\t\t\t\t\tsize_t i;\n\t\t\t\t\tfor (i = 0; i < benchedsize; i++)\n\t\t\t\t\t\tout_buff[i] = (char)i;\n\t\t\t\t}\t\t\t\t// warmimg up memory\n\n\t\t\t\tnb_loops = 0;\n\t\t\t\tmilliTime = BMK_GetMilliStart();\n\t\t\t\twhile (BMK_GetMilliStart() == milliTime) ;\n\t\t\t\tmilliTime = BMK_GetMilliStart();\n\t\t\t\twhile (BMK_GetMilliSpan(milliTime) < TIMELOOP) {\n\t\t\t\t\tfor (chunkNb = 0; chunkNb < nbChunks; chunkNb++)\n\t\t\t\t\t\tchunkP[chunkNb].outputSize = compP.compressionFunction(chunkP[chunkNb].inputBuffer, chunkP[chunkNb].outputBuffer, chunkP[chunkNb].inputSize);\n\t\t\t\t\tnb_loops++;\n\t\t\t\t}\n\t\t\t\tmilliTime = BMK_GetMilliSpan(milliTime);\n\n\t\t\t\tif ((double)milliTime < fastestC * nb_loops)\n\t\t\t\t\tfastestC = (double)milliTime / nb_loops;\n\t\t\t\tcSize = 0;\n\t\t\t\tfor (chunkNb = 0; chunkNb < nbChunks; chunkNb++)\n\t\t\t\t\tcSize += chunkP[chunkNb].outputSize;\n\t\t\t\tratio = (double)cSize / (double)benchedsize *100.;\n\n\t\t\t\tDISPLAY(\"%1i-%-14.14s : %9i -> %9i (%5.2f%%), %6.1f MB/s\\r\", loopNb, infilename, (int)benchedsize, (int)cSize, ratio, (double)benchedsize / fastestC / 1000.);\n\n\t\t\t\t// Decompression\n\t\t\t\t{\n\t\t\t\t\tsize_t i;\n\t\t\t\t\tfor (i = 0; i < benchedsize; i++)\n\t\t\t\t\t\tin_buff[i] = 0;\n\t\t\t\t}\t\t\t\t// zeroing area, for CRC checking\n\n\t\t\t\tnb_loops = 0;\n\t\t\t\tmilliTime = BMK_GetMilliStart();\n\t\t\t\twhile (BMK_GetMilliStart() == milliTime) ;\n\t\t\t\tmilliTime = BMK_GetMilliStart();\n\t\t\t\twhile (BMK_GetMilliSpan(milliTime) < TIMELOOP) {\n\t\t\t\t\tfor (chunkNb = 0; chunkNb < nbChunks; chunkNb++)\n\t\t\t\t\t\tchunkP[chunkNb].outputSize = compP.decompressionFunction(chunkP[chunkNb].outputBuffer, chunkP[chunkNb].inputBuffer, chunkP[chunkNb].inputSize);\n\t\t\t\t\tnb_loops++;\n\t\t\t\t}\n\t\t\t\tmilliTime = BMK_GetMilliSpan(milliTime);\n\n\t\t\t\tif ((double)milliTime < fastestD * nb_loops)\n\t\t\t\t\tfastestD = (double)milliTime / nb_loops;\n\t\t\t\tDISPLAY(\"%1i-%-14.14s : %9i -> %9i (%5.2f%%), %6.1f MB/s , %6.1f MB/s\\r\", loopNb, infilename, (int)benchedsize, (int)cSize, ratio, (double)benchedsize / fastestC / 1000., (double)benchedsize / fastestD / 1000.);\n\n\t\t\t\t// CRC Checking\n\t\t\t\tcrcd = BMK_checksum_MMH3A(in_buff, benchedsize);\n\t\t\t\tif (crcc != crcd) {\n\t\t\t\t\tDISPLAY(\"\\n!!! WARNING !!! %14s : Invalid Checksum : %x != %x\\n\", infilename, (unsigned)crcc, (unsigned)crcd);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (crcc == crcd) {\n\t\t\t\tif (ratio < 100.)\n\t\t\t\t\tDISPLAY(\"%-16.16s : %9i -> %9i (%5.2f%%), %6.1f MB/s , %6.1f MB/s\\n\", infilename, (int)benchedsize, (int)cSize, ratio, (double)benchedsize / fastestC / 1000., (double)benchedsize / fastestD / 1000.);\n\t\t\t\telse\n\t\t\t\t\tDISPLAY(\"%-16.16s : %9i -> %9i (%5.1f%%), %6.1f MB/s , %6.1f MB/s \\n\", infilename, (int)benchedsize, (int)cSize, ratio, (double)benchedsize / fastestC / 1000., (double)benchedsize / fastestD / 1000.);\n\t\t\t}\n\t\t\ttotals += benchedsize;\n\t\t\ttotalz += cSize;\n\t\t\ttotalc += fastestC;\n\t\t\ttotald += fastestD;\n\t\t}\n\n\t\tfree(in_buff);\n\t\tfree(out_buff);\n\t\tfree(chunkP);\n\t}\n\n\tif (nbFiles > 1)\n\t\tprintf(\"%-16.16s :%10llu ->%10llu (%5.2f%%), %6.1f MB/s , %6.1f MB/s\\n\", \"  TOTAL\", (long long unsigned int)totals, (long long unsigned int)totalz, (double)totalz / (double)totals * 100., (double)totals / totalc / 1000., (double)totals / totald / 1000.);\n\n\treturn 0;\n}\n"
  },
  {
    "path": "src/lz4/lz4.c",
    "content": "/*\n   LZ4 - Fast LZ compression algorithm\n   Copyright (C) 2011-2012, Yann Collet.\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\n   - LZ4 source repository : http://code.google.com/p/lz4/\n*/\n\n//**************************************\n// Tuning parameters\n//**************************************\n// COMPRESSIONLEVEL :\n// Increasing this value improves compression ratio\n// Lowering this value reduces memory usage\n// Reduced memory usage typically improves speed, due to cache effect (ex : L1 32KB for Intel, L1 64KB for AMD)\n// Memory usage formula : N->2^(N+2) Bytes (examples : 12 -> 16KB ; 17 -> 512KB)\n#define COMPRESSIONLEVEL 12\n\n// NOTCOMPRESSIBLE_CONFIRMATION :\n// Decreasing this value will make the algorithm skip faster data segments considered \"incompressible\"\n// This may decrease compression ratio dramatically, but will be faster on incompressible data\n// Increasing this value will make the algorithm search more before declaring a segment \"incompressible\"\n// This could improve compression a bit, but will be slower on incompressible data\n// The default value (6) is recommended\n#define NOTCOMPRESSIBLE_CONFIRMATION 6\n\n// LZ4_COMPRESSMIN :\n// Compression function will *fail* if it is not successful at compressing input by at least LZ4_COMPRESSMIN bytes\n// Since the compression function stops working prematurely, it results in a speed gain\n// The output however is unusable. Compression function result will be zero.\n// Default : 0 = disabled\n#define LZ4_COMPRESSMIN 0\n\n// BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE :\n// This will provide a boost to performance for big endian cpu, but the resulting compressed stream will be incompatible with little-endian CPU.\n// You can set this option to 1 in situations where data will stay within closed environment\n// This option is useless on Little_Endian CPU (such as x86)\n//#define BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE 1\n\n//**************************************\n// CPU Feature Detection\n//**************************************\n// 32 or 64 bits ?\n#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) )\t// Detects 64 bits mode\n#    define LZ4_ARCH64 1\n#else\n#    define LZ4_ARCH64 0\n#endif\n\n// Little Endian or Big Endian ?\n// Note : overwrite the below #define if you know your architecture endianess\n#if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) || defined(PPC) || defined(__powerpc__) || defined(__powerpc) || defined(powerpc) || ((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) )\n#    define LZ4_BIG_ENDIAN 1\n#else\n// Little Endian assumed. PDP Endian and other very rare endian format are unsupported.\n#endif\n\n// Unaligned memory access is automatically enabled for \"common\" CPU, such as x86.\n// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected\n// If you know your target CPU supports unaligned memory access, you may want to force this option manually to improve performance\n#if defined(__ARM_FEATURE_UNALIGNED)\n#    define LZ4_FORCE_UNALIGNED_ACCESS 1\n#endif\n\n// Define this parameter if your target system or compiler does not support hardware bit count\n#if defined(_MSC_VER) && defined(_WIN32_WCE)\t// Visual Studio for Windows CE does not support Hardware bit count\n#    define LZ4_FORCE_SW_BITCOUNT\n#endif\n\n//**************************************\n// Compiler Options\n//**************************************\n#if __STDC_VERSION__ >= 199901L\t// C99\n/* \"restrict\" is a known keyword */\n#else\n#    define restrict\t\t\t// Disable restrict\n#endif\n\n#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n\n#ifdef _MSC_VER\t\t\t\t\t// Visual Studio\n#    define inline __forceinline// Visual is not C99, but supports some kind of inline\n#    if LZ4_ARCH64\t\t\t\t// 64-bit\n#        pragma intrinsic(_BitScanForward64)\n\t\t\t\t\t\t\t\t\t\t// For Visual 2005\n#        pragma intrinsic(_BitScanReverse64)\n\t\t\t\t\t\t\t\t\t\t// For Visual 2005\n#    else\n#        pragma intrinsic(_BitScanForward)\n\t\t\t\t\t\t\t\t\t// For Visual 2005\n#        pragma intrinsic(_BitScanReverse)\n\t\t\t\t\t\t\t\t\t// For Visual 2005\n#    endif\n#endif\n\n#ifdef _MSC_VER\n#    define lz4_bswap16(x) _byteswap_ushort(x)\n#else\n#    define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8)))\n#endif\n\n#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)\n#    define expect(expr,value)    (__builtin_expect ((expr),(value)) )\n#else\n#    define expect(expr,value)    (expr)\n#endif\n\n#define likely(expr)     expect((expr) != 0, 1)\n#define unlikely(expr)   expect((expr) != 0, 0)\n\n//**************************************\n// Includes\n//**************************************\n#include <stdlib.h>\t\t\t\t// for malloc\n#include <string.h>\t\t\t\t// for memset\n#include \"lz4.h\"\n\n//**************************************\n// Basic Types\n//**************************************\n#if defined(_MSC_VER)\t\t\t// Visual Studio does not support 'stdint' natively\n#    define BYTE\tunsigned __int8\n#    define U16\t\tunsigned __int16\n#    define U32\t\tunsigned __int32\n#    define S32\t\t__int32\n#    define U64\t\tunsigned __int64\n#else\n#    include <stdint.h>\n#    define BYTE\tuint8_t\n#    define U16\t\tuint16_t\n#    define U32\t\tuint32_t\n#    define S32\t\tint32_t\n#    define U64\t\tuint64_t\n#endif\n\n#ifndef LZ4_FORCE_UNALIGNED_ACCESS\n#    pragma pack(push, 1)\n#endif\n\ntypedef struct _U16_S {\n\tU16 v;\n} U16_S;\ntypedef struct _U32_S {\n\tU32 v;\n} U32_S;\ntypedef struct _U64_S {\n\tU64 v;\n} U64_S;\n\n#ifndef LZ4_FORCE_UNALIGNED_ACCESS\n#    pragma pack(pop)\n#endif\n\n#define A64(x) (((U64_S *)(x))->v)\n#define A32(x) (((U32_S *)(x))->v)\n#define A16(x) (((U16_S *)(x))->v)\n\n//**************************************\n// Constants\n//**************************************\n#define MINMATCH 4\n\n#define HASH_LOG COMPRESSIONLEVEL\n#define HASHTABLESIZE (1 << HASH_LOG)\n#define HASH_MASK (HASHTABLESIZE - 1)\n\n#define SKIPSTRENGTH (NOTCOMPRESSIBLE_CONFIRMATION>2?NOTCOMPRESSIBLE_CONFIRMATION:2)\n#define STACKLIMIT 13\n#define HEAPMODE (HASH_LOG>STACKLIMIT)\t// Defines if memory is allocated into the stack (local variable), or into the heap (malloc()).\n#define COPYLENGTH 8\n#define LASTLITERALS 5\n#define MFLIMIT (COPYLENGTH+MINMATCH)\n#define MINLENGTH (MFLIMIT+1)\n\n#define MAXD_LOG 16\n#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)\n\n#define ML_BITS 4\n#define ML_MASK ((1U<<ML_BITS)-1)\n#define RUN_BITS (8-ML_BITS)\n#define RUN_MASK ((1U<<RUN_BITS)-1)\n\n//**************************************\n// Architecture-specific macros\n//**************************************\n#if LZ4_ARCH64\t\t\t\t\t// 64-bit\n#    define STEPSIZE 8\n#    define UARCH U64\n#    define AARCH A64\n#    define LZ4_COPYSTEP(s,d)\t\tA64(d) = A64(s); d+=8; s+=8;\n#    define LZ4_COPYPACKET(s,d)\t\tLZ4_COPYSTEP(s,d)\n#    define LZ4_SECURECOPY(s,d,e)\tif (d<e) LZ4_WILDCOPY(s,d,e)\n#    define HTYPE U32\n#    define INITBASE(base)\t\t\tconst BYTE* const base = ip\n#else // 32-bit\n#    define STEPSIZE 4\n#    define UARCH U32\n#    define AARCH A32\n#    define LZ4_COPYSTEP(s,d)\t\tA32(d) = A32(s); d+=4; s+=4;\n#    define LZ4_COPYPACKET(s,d)\t\tLZ4_COPYSTEP(s,d); LZ4_COPYSTEP(s,d);\n#    define LZ4_SECURECOPY\t\t\tLZ4_WILDCOPY\n#    define HTYPE const BYTE*\n#    define INITBASE(base)\t\t\tconst int base = 0\n#endif\n\n#if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE))\n#    define LZ4_READ_LITTLEENDIAN_16(d,s,p) { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }\n#    define LZ4_WRITE_LITTLEENDIAN_16(p,i)  { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p+=2; }\n#else // Little Endian\n#    define LZ4_READ_LITTLEENDIAN_16(d,s,p) { d = (s) - A16(p); }\n#    define LZ4_WRITE_LITTLEENDIAN_16(p,v)  { A16(p) = v; p+=2; }\n#endif\n\n//**************************************\n// Local structures\n//**************************************\nstruct refTables {\n\tHTYPE hashTable[HASHTABLESIZE];\n};\n\n//**************************************\n// Macros\n//**************************************\n#define LZ4_HASH_FUNCTION(i)\t(((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))\n#define LZ4_HASH_VALUE(p)\t\tLZ4_HASH_FUNCTION(A32(p))\n#define LZ4_WILDCOPY(s,d,e)\t\tdo { LZ4_COPYPACKET(s,d) } while (d<e);\n#define LZ4_BLINDCOPY(s,d,l)\t{ BYTE* e=(d)+l; LZ4_WILDCOPY(s,d,e); d=e; }\n\n//****************************\n// Private functions\n//****************************\n#if LZ4_ARCH64\n\ninline static int LZ4_NbCommonBytes(register U64 val) {\n#    if defined(LZ4_BIG_ENDIAN)\n#        if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\tunsigned long r = 0;\n\t_BitScanReverse64(&r, val);\n\treturn (int)(r >> 3);\n#        elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\treturn (__builtin_clzll(val) >> 3);\n#        else\n\tint r;\n\tif (!(val >> 32)) {\n\t\tr = 4;\n\t} else {\n\t\tr = 0;\n\t\tval >>= 32;\n\t}\n\tif (!(val >> 16)) {\n\t\tr += 2;\n\t\tval >>= 8;\n\t} else {\n\t\tval >>= 24;\n\t}\n\tr += (!val);\n\treturn r;\n#        endif\n#    else\n#        if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\tunsigned long r = 0;\n\t_BitScanForward64(&r, val);\n\treturn (int)(r >> 3);\n#        elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\treturn (__builtin_ctzll(val) >> 3);\n#        else\n\tstatic const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };\n\treturn DeBruijnBytePos[((U64) ((val & -val) * 0x0218A392CDABBD3F)) >> 58];\n#        endif\n#    endif\n}\n\n#else\n\ninline static int LZ4_NbCommonBytes(register U32 val) {\n#    if defined(LZ4_BIG_ENDIAN)\n#        if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\tunsigned long r = 0;\n\t_BitScanReverse(&r, val);\n\treturn (int)(r >> 3);\n#        elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\treturn (__builtin_clz(val) >> 3);\n#        else\n\tint r;\n\tif (!(val >> 16)) {\n\t\tr = 2;\n\t\tval >>= 8;\n\t} else {\n\t\tr = 0;\n\t\tval >>= 24;\n\t}\n\tr += (!val);\n\treturn r;\n#        endif\n#    else\n#        if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\tunsigned long r = 0;\n\t_BitScanForward(&r, val);\n\treturn (int)(r >> 3);\n#        elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\treturn (__builtin_ctz(val) >> 3);\n#        else\n\tstatic const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };\n\treturn DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27];\n#        endif\n#    endif\n}\n\n#endif\n\n//****************************\n// Public functions\n//****************************\n\nint LZ4_compressBound(int isize) {\n\treturn (isize + (isize / 255) + 16);\n}\n\n//******************************\n// Compression functions\n//******************************\n\nint LZ4_compressCtx(void **ctx, const char *source, char *dest, int isize) {\n#if HEAPMODE\n\tstruct refTables *srt = (struct refTables *)(*ctx);\n\tHTYPE *HashTable;\n#else\n\tHTYPE HashTable[HASHTABLESIZE] = { 0 };\n#endif\n\n\tconst BYTE *ip = (BYTE *) source;\n\tINITBASE(base);\n\tconst BYTE *anchor = ip;\n\tconst BYTE *const iend = ip + isize;\n\tconst BYTE *const mflimit = iend - MFLIMIT;\n#define matchlimit (iend - LASTLITERALS)\n\n\tBYTE *op = (BYTE *) dest;\n\n\tint len, length;\n\tconst int skipStrength = SKIPSTRENGTH;\n\tU32 forwardH;\n\n\t// Init\n\tif (isize < MINLENGTH)\n\t\tgoto _last_literals;\n#if HEAPMODE\n\tif (*ctx == NULL) {\n\t\tsrt = (struct refTables *)malloc(sizeof(struct refTables));\n\t\t*ctx = (void *)srt;\n\t}\n\tHashTable = (HTYPE *) (srt->hashTable);\n\tmemset((void *)HashTable, 0, sizeof(srt->hashTable));\n#else\n\t(void)ctx;\n#endif\n\n\t// First Byte\n\tHashTable[LZ4_HASH_VALUE(ip)] = ip - base;\n\tip++;\n\tforwardH = LZ4_HASH_VALUE(ip);\n\n\t// Main Loop\n\tfor (;;) {\n\t\tint findMatchAttempts = (1U << skipStrength) + 3;\n\t\tconst BYTE *forwardIp = ip;\n\t\tconst BYTE *ref;\n\t\tBYTE *token;\n\n\t\t// Find a match\n\t\tdo {\n\t\t\tU32 h = forwardH;\n\t\t\tint step = findMatchAttempts++ >> skipStrength;\n\t\t\tip = forwardIp;\n\t\t\tforwardIp = ip + step;\n\n\t\t\tif unlikely\n\t\t\t\t(forwardIp > mflimit) {\n\t\t\t\tgoto _last_literals;\n\t\t\t\t}\n\n\t\t\tforwardH = LZ4_HASH_VALUE(forwardIp);\n\t\t\tref = base + HashTable[h];\n\t\t\tHashTable[h] = ip - base;\n\n\t\t} while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip)));\n\n\t\t// Catch up\n\t\twhile ((ip > anchor) && (ref > (BYTE *) source) && unlikely(ip[-1] == ref[-1])) {\n\t\t\tip--;\n\t\t\tref--;\n\t\t}\n\n\t\t// Encode Literal length\n\t\tlength = ip - anchor;\n\t\ttoken = op++;\n\t\tif (length >= (int)RUN_MASK) {\n\t\t\t*token = (RUN_MASK << ML_BITS);\n\t\t\tlen = length - RUN_MASK;\n\t\t\tfor (; len > 254; len -= 255)\n\t\t\t\t*op++ = 255;\n\t\t\t*op++ = (BYTE) len;\n\t\t} else\n\t\t\t*token = (length << ML_BITS);\n\n\t\t// Copy Literals\n\t\tLZ4_BLINDCOPY(anchor, op, length);\n\n _next_match:\n\t\t// Encode Offset\n\t\tLZ4_WRITE_LITTLEENDIAN_16(op, ip - ref);\n\n\t\t// Start Counting\n\t\tip += MINMATCH;\n\t\tref += MINMATCH;\t\t// MinMatch verified\n\t\tanchor = ip;\n\t\twhile likely\n\t\t\t(ip < matchlimit - (STEPSIZE - 1)) {\n\t\t\tUARCH diff = AARCH(ref) ^ AARCH(ip);\n\t\t\tif (!diff) {\n\t\t\t\tip += STEPSIZE;\n\t\t\t\tref += STEPSIZE;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tip += LZ4_NbCommonBytes(diff);\n\t\t\tgoto _endCount;\n\t\t\t}\n\t\tif (LZ4_ARCH64)\n\t\t\tif ((ip < (matchlimit - 3)) && (A32(ref) == A32(ip))) {\n\t\t\t\tip += 4;\n\t\t\t\tref += 4;\n\t\t\t}\n\t\tif ((ip < (matchlimit - 1)) && (A16(ref) == A16(ip))) {\n\t\t\tip += 2;\n\t\t\tref += 2;\n\t\t}\n\t\tif ((ip < matchlimit) && (*ref == *ip))\n\t\t\tip++;\n _endCount:\n\n\t\t// Encode MatchLength\n\t\tlen = (ip - anchor);\n\t\tif (len >= (int)ML_MASK) {\n\t\t\t*token += ML_MASK;\n\t\t\tlen -= ML_MASK;\n\t\t\tfor (; len > 509; len -= 510) {\n\t\t\t\t*op++ = 255;\n\t\t\t\t*op++ = 255;\n\t\t\t}\n\t\t\tif (len > 254) {\n\t\t\t\tlen -= 255;\n\t\t\t\t*op++ = 255;\n\t\t\t}\n\t\t\t*op++ = (BYTE) len;\n\t\t} else\n\t\t\t*token += len;\n\n\t\t// Test end of chunk\n\t\tif (ip > mflimit) {\n\t\t\tanchor = ip;\n\t\t\tbreak;\n\t\t}\n\t\t// Fill table\n\t\tHashTable[LZ4_HASH_VALUE(ip - 2)] = ip - 2 - base;\n\n\t\t// Test next position\n\t\tref = base + HashTable[LZ4_HASH_VALUE(ip)];\n\t\tHashTable[LZ4_HASH_VALUE(ip)] = ip - base;\n\t\tif ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) {\n\t\t\ttoken = op++;\n\t\t\t*token = 0;\n\t\t\tgoto _next_match;\n\t\t}\n\t\t// Prepare next loop\n\t\tanchor = ip++;\n\t\tforwardH = LZ4_HASH_VALUE(ip);\n\t}\n\n _last_literals:\n\t// Encode Last Literals\n\t{\n\t\tint lastRun = iend - anchor;\n\t\tif ((LZ4_COMPRESSMIN > 0) && (((op - (BYTE *) dest) + lastRun + 1 + ((lastRun - 15) / 255)) > isize - LZ4_COMPRESSMIN))\n\t\t\treturn 0;\n\t\tif (lastRun >= (int)RUN_MASK) {\n\t\t\t*op++ = (RUN_MASK << ML_BITS);\n\t\t\tlastRun -= RUN_MASK;\n\t\t\tfor (; lastRun > 254; lastRun -= 255)\n\t\t\t\t*op++ = 255;\n\t\t\t*op++ = (BYTE) lastRun;\n\t\t} else\n\t\t\t*op++ = (lastRun << ML_BITS);\n\t\tmemcpy(op, anchor, iend - anchor);\n\t\top += iend - anchor;\n\t}\n\n\t// End\n\treturn (int)(((char *)op) - dest);\n}\n\n// Note : this function is valid only if isize < LZ4_64KLIMIT\n#define LZ4_64KLIMIT ((1<<16) + (MFLIMIT-1))\n#define HASHLOG64K (HASH_LOG+1)\n#define HASH64KTABLESIZE (1U<<HASHLOG64K)\n#define LZ4_HASH64K_FUNCTION(i)\t(((i) * 2654435761U) >> ((MINMATCH*8)-HASHLOG64K))\n#define LZ4_HASH64K_VALUE(p)\tLZ4_HASH64K_FUNCTION(A32(p))\nint LZ4_compress64kCtx(void **ctx, const char *source, char *dest, int isize) {\n#if HEAPMODE\n\tstruct refTables *srt = (struct refTables *)(*ctx);\n\tU16 *HashTable;\n#else\n\tU16 HashTable[HASH64KTABLESIZE] = { 0 };\n#endif\n\n\tconst BYTE *ip = (BYTE *) source;\n\tconst BYTE *anchor = ip;\n\tconst BYTE *const base = ip;\n\tconst BYTE *const iend = ip + isize;\n\tconst BYTE *const mflimit = iend - MFLIMIT;\n#define matchlimit (iend - LASTLITERALS)\n\n\tBYTE *op = (BYTE *) dest;\n\n\tint len, length;\n\tconst int skipStrength = SKIPSTRENGTH;\n\tU32 forwardH;\n\n\t// Init\n\tif (isize < MINLENGTH)\n\t\tgoto _last_literals;\n#if HEAPMODE\n\tif (*ctx == NULL) {\n\t\tsrt = (struct refTables *)malloc(sizeof(struct refTables));\n\t\t*ctx = (void *)srt;\n\t}\n\tHashTable = (U16 *) (srt->hashTable);\n\tmemset((void *)HashTable, 0, sizeof(srt->hashTable));\n#else\n\t(void)ctx;\n#endif\n\n\t// First Byte\n\tip++;\n\tforwardH = LZ4_HASH64K_VALUE(ip);\n\n\t// Main Loop\n\tfor (;;) {\n\t\tint findMatchAttempts = (1U << skipStrength) + 3;\n\t\tconst BYTE *forwardIp = ip;\n\t\tconst BYTE *ref;\n\t\tBYTE *token;\n\n\t\t// Find a match\n\t\tdo {\n\t\t\tU32 h = forwardH;\n\t\t\tint step = findMatchAttempts++ >> skipStrength;\n\t\t\tip = forwardIp;\n\t\t\tforwardIp = ip + step;\n\n\t\t\tif (forwardIp > mflimit) {\n\t\t\t\tgoto _last_literals;\n\t\t\t}\n\n\t\t\tforwardH = LZ4_HASH64K_VALUE(forwardIp);\n\t\t\tref = base + HashTable[h];\n\t\t\tHashTable[h] = ip - base;\n\n\t\t} while (A32(ref) != A32(ip));\n\n\t\t// Catch up\n\t\twhile ((ip > anchor) && (ref > (BYTE *) source) && (ip[-1] == ref[-1])) {\n\t\t\tip--;\n\t\t\tref--;\n\t\t}\n\n\t\t// Encode Literal length\n\t\tlength = ip - anchor;\n\t\ttoken = op++;\n\t\tif (length >= (int)RUN_MASK) {\n\t\t\t*token = (RUN_MASK << ML_BITS);\n\t\t\tlen = length - RUN_MASK;\n\t\t\tfor (; len > 254; len -= 255)\n\t\t\t\t*op++ = 255;\n\t\t\t*op++ = (BYTE) len;\n\t\t} else\n\t\t\t*token = (length << ML_BITS);\n\n\t\t// Copy Literals\n\t\tLZ4_BLINDCOPY(anchor, op, length);\n\n _next_match:\n\t\t// Encode Offset\n\t\tLZ4_WRITE_LITTLEENDIAN_16(op, ip - ref);\n\n\t\t// Start Counting\n\t\tip += MINMATCH;\n\t\tref += MINMATCH;\t\t// MinMatch verified\n\t\tanchor = ip;\n\t\twhile (ip < matchlimit - (STEPSIZE - 1)) {\n\t\t\tUARCH diff = AARCH(ref) ^ AARCH(ip);\n\t\t\tif (!diff) {\n\t\t\t\tip += STEPSIZE;\n\t\t\t\tref += STEPSIZE;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tip += LZ4_NbCommonBytes(diff);\n\t\t\tgoto _endCount;\n\t\t}\n\t\tif (LZ4_ARCH64)\n\t\t\tif ((ip < (matchlimit - 3)) && (A32(ref) == A32(ip))) {\n\t\t\t\tip += 4;\n\t\t\t\tref += 4;\n\t\t\t}\n\t\tif ((ip < (matchlimit - 1)) && (A16(ref) == A16(ip))) {\n\t\t\tip += 2;\n\t\t\tref += 2;\n\t\t}\n\t\tif ((ip < matchlimit) && (*ref == *ip))\n\t\t\tip++;\n _endCount:\n\n\t\t// Encode MatchLength\n\t\tlen = (ip - anchor);\n\t\tif (len >= (int)ML_MASK) {\n\t\t\t*token += ML_MASK;\n\t\t\tlen -= ML_MASK;\n\t\t\tfor (; len > 509; len -= 510) {\n\t\t\t\t*op++ = 255;\n\t\t\t\t*op++ = 255;\n\t\t\t}\n\t\t\tif (len > 254) {\n\t\t\t\tlen -= 255;\n\t\t\t\t*op++ = 255;\n\t\t\t}\n\t\t\t*op++ = (BYTE) len;\n\t\t} else\n\t\t\t*token += len;\n\n\t\t// Test end of chunk\n\t\tif (ip > mflimit) {\n\t\t\tanchor = ip;\n\t\t\tbreak;\n\t\t}\n\t\t// Fill table\n\t\tHashTable[LZ4_HASH64K_VALUE(ip - 2)] = ip - 2 - base;\n\n\t\t// Test next position\n\t\tref = base + HashTable[LZ4_HASH64K_VALUE(ip)];\n\t\tHashTable[LZ4_HASH64K_VALUE(ip)] = ip - base;\n\t\tif (A32(ref) == A32(ip)) {\n\t\t\ttoken = op++;\n\t\t\t*token = 0;\n\t\t\tgoto _next_match;\n\t\t}\n\t\t// Prepare next loop\n\t\tanchor = ip++;\n\t\tforwardH = LZ4_HASH64K_VALUE(ip);\n\t}\n\n _last_literals:\n\t// Encode Last Literals\n\t{\n\t\tint lastRun = iend - anchor;\n\t\tif ((LZ4_COMPRESSMIN > 0) && (((op - (BYTE *) dest) + lastRun + 1 + ((lastRun - 15) / 255)) > isize - LZ4_COMPRESSMIN))\n\t\t\treturn 0;\n\t\tif (lastRun >= (int)RUN_MASK) {\n\t\t\t*op++ = (RUN_MASK << ML_BITS);\n\t\t\tlastRun -= RUN_MASK;\n\t\t\tfor (; lastRun > 254; lastRun -= 255)\n\t\t\t\t*op++ = 255;\n\t\t\t*op++ = (BYTE) lastRun;\n\t\t} else\n\t\t\t*op++ = (lastRun << ML_BITS);\n\t\tmemcpy(op, anchor, iend - anchor);\n\t\top += iend - anchor;\n\t}\n\n\t// End\n\treturn (int)(((char *)op) - dest);\n}\n\nint LZ4_compress(const char *source, char *dest, int isize) {\n#if HEAPMODE\n\tvoid *ctx = malloc(sizeof(struct refTables));\n\tint result;\n\tif (isize < LZ4_64KLIMIT)\n\t\tresult = LZ4_compress64kCtx(&ctx, source, dest, isize);\n\telse\n\t\tresult = LZ4_compressCtx(&ctx, source, dest, isize);\n\tfree(ctx);\n\treturn result;\n#else\n\tif (isize < (int)LZ4_64KLIMIT)\n\t\treturn LZ4_compress64kCtx(NULL, source, dest, isize);\n\treturn LZ4_compressCtx(NULL, source, dest, isize);\n#endif\n}\n\n//****************************\n// Decompression functions\n//****************************\n\n// Note : The decoding functions LZ4_uncompress() and LZ4_uncompress_unknownOutputSize()\n//      are safe against \"buffer overflow\" attack type.\n//      They will never write nor read outside of the provided output buffers.\n//      LZ4_uncompress_unknownOutputSize() also insures that it will never read outside of the input buffer.\n//      A corrupted input will produce an error result, a negative int, indicating the position of the error within input stream.\n\nint LZ4_uncompress(const char *source, char *dest, int osize) {\n\t// Local Variables\n\tconst BYTE *restrict ip = (const BYTE *)source;\n\tconst BYTE *restrict ref;\n\n\tBYTE *restrict op = (BYTE *) dest;\n\tBYTE *const oend = op + osize;\n\tBYTE *cpy;\n\n\tBYTE token;\n\n\tint len, length;\n\tsize_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };\n\n\t// Main Loop\n\twhile (1) {\n\t\t// get runlength\n\t\ttoken = *ip++;\n\t\tif ((length = (token >> ML_BITS)) == RUN_MASK) {\n\t\t\tfor (; (len = *ip++) == 255; length += 255) {\n\t\t\t}\n\t\t\tlength += len;\n\t\t}\n\t\t// copy literals\n\t\tcpy = op + length;\n\t\tif unlikely\n\t\t\t(cpy > oend - COPYLENGTH) {\n\t\t\tif (cpy > oend)\n\t\t\t\tgoto _output_error;\t// Error : request to write beyond destination buffer\n\t\t\tmemcpy(op, ip, length);\n\t\t\tip += length;\n\t\t\tbreak;\t\t\t\t// Necessarily EOF\n\t\t\t}\n\t\tLZ4_WILDCOPY(ip, op, cpy);\n\t\tip -= (op - cpy);\n\t\top = cpy;\n\n\t\t// get offset\n\t\tLZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);\n\t\tip += 2;\n\t\tif (ref < (BYTE * const)dest)\n\t\t\tgoto _output_error;\t// Error : offset create reference outside destination buffer\n\n\t\t// get matchlength\n\t\tif ((length = (token & ML_MASK)) == ML_MASK) {\n\t\t\tfor (; *ip == 255; length += 255) {\n\t\t\t\tip++;\n\t\t\t}\n\t\t\tlength += *ip++;\n\t\t}\n\t\t// copy repeated sequence\n\t\tif unlikely\n\t\t\t(op - ref < STEPSIZE) {\n#if LZ4_ARCH64\n\t\t\tsize_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };\n\t\t\tsize_t dec2 = dec2table[op - ref];\n#else\n\t\t\tconst int dec2 = 0;\n#endif\n\t\t\t*op++ = *ref++;\n\t\t\t*op++ = *ref++;\n\t\t\t*op++ = *ref++;\n\t\t\t*op++ = *ref++;\n\t\t\tref -= dec[op - ref];\n\t\t\tA32(op) = A32(ref);\n\t\t\top += STEPSIZE - 4;\n\t\t\tref -= dec2;\n\t\t} else {\n\t\t\tLZ4_COPYSTEP(ref, op);\n\t\t}\n\t\tcpy = op + length - (STEPSIZE - 4);\n\t\tif (cpy > oend - COPYLENGTH) {\n\t\t\tif (cpy > oend)\n\t\t\t\tgoto _output_error;\t// Error : request to write beyond destination buffer\n\t\t\tLZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));\n\t\t\twhile (op < cpy)\n\t\t\t\t*op++ = *ref++;\n\t\t\top = cpy;\n\t\t\tif (op == oend)\n\t\t\t\tbreak;\t\t\t// Check EOF (should never happen, since last 5 bytes are supposed to be literals)\n\t\t\tcontinue;\n\t\t}\n\t\tLZ4_SECURECOPY(ref, op, cpy);\n\t\top = cpy;\t\t\t\t// correction\n\t}\n\n\t// end of decoding\n\treturn (int)(((char *)ip) - source);\n\n\t// write overflow error detected\n _output_error:\n\treturn (int)(-(((char *)ip) - source));\n}\n\nint LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize, int maxOutputSize) {\n\t// Local Variables\n\tconst BYTE *restrict ip = (const BYTE *)source;\n\tconst BYTE *const iend = ip + isize;\n\tconst BYTE *restrict ref;\n\n\tBYTE *restrict op = (BYTE *) dest;\n\tBYTE *const oend = op + maxOutputSize;\n\tBYTE *cpy;\n\n\tsize_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };\n\n\t// Main Loop\n\twhile (ip < iend) {\n\t\tBYTE token;\n\t\tint length;\n\n\t\t// get runlength\n\t\ttoken = *ip++;\n\t\tif ((length = (token >> ML_BITS)) == RUN_MASK) {\n\t\t\tint s = 255;\n\t\t\twhile ((ip < iend) && (s == 255)) {\n\t\t\t\ts = *ip++;\n\t\t\t\tlength += s;\n\t\t\t}\n\t\t}\n\t\t// copy literals\n\t\tcpy = op + length;\n\t\tif ((cpy > oend - COPYLENGTH) || (ip + length > iend - COPYLENGTH)) {\n\t\t\tif (cpy > oend)\n\t\t\t\tgoto _output_error;\t// Error : request to write beyond destination buffer\n\t\t\tif (ip + length > iend)\n\t\t\t\tgoto _output_error;\t// Error : request to read beyond source buffer\n\t\t\tmemcpy(op, ip, length);\n\t\t\top += length;\n\t\t\tip += length;\n\t\t\tif (ip < iend)\n\t\t\t\tgoto _output_error;\t// Error : LZ4 format violation\n\t\t\tbreak;\t\t\t\t// Necessarily EOF, due to parsing restrictions\n\t\t}\n\t\tLZ4_WILDCOPY(ip, op, cpy);\n\t\tip -= (op - cpy);\n\t\top = cpy;\n\n\t\t// get offset\n\t\tLZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);\n\t\tip += 2;\n\t\tif (ref < (BYTE * const)dest)\n\t\t\tgoto _output_error;\t// Error : offset creates reference outside of destination buffer\n\n\t\t// get matchlength\n\t\tif ((length = (token & ML_MASK)) == ML_MASK) {\n\t\t\twhile (ip < iend) {\n\t\t\t\tint s = *ip++;\n\t\t\t\tlength += s;\n\t\t\t\tif (s == 255)\n\t\t\t\t\tcontinue;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t// copy repeated sequence\n\t\tif unlikely\n\t\t\t(op - ref < STEPSIZE) {\n#if LZ4_ARCH64\n\t\t\tsize_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };\n\t\t\tsize_t dec2 = dec2table[op - ref];\n#else\n\t\t\tconst int dec2 = 0;\n#endif\n\t\t\t*op++ = *ref++;\n\t\t\t*op++ = *ref++;\n\t\t\t*op++ = *ref++;\n\t\t\t*op++ = *ref++;\n\t\t\tref -= dec[op - ref];\n\t\t\tA32(op) = A32(ref);\n\t\t\top += STEPSIZE - 4;\n\t\t\tref -= dec2;\n\t\t} else {\n\t\t\tLZ4_COPYSTEP(ref, op);\n\t\t}\n\t\tcpy = op + length - (STEPSIZE - 4);\n\t\tif (cpy > oend - COPYLENGTH) {\n\t\t\tif (cpy > oend)\n\t\t\t\tgoto _output_error;\t// Error : request to write outside of destination buffer\n\t\t\tLZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));\n\t\t\twhile (op < cpy)\n\t\t\t\t*op++ = *ref++;\n\t\t\top = cpy;\n\t\t\tif (op == oend)\n\t\t\t\tbreak;\t\t\t// Check EOF (should never happen, since last 5 bytes are supposed to be literals)\n\t\t\tcontinue;\n\t\t}\n\t\tLZ4_SECURECOPY(ref, op, cpy);\n\t\top = cpy;\t\t\t\t// correction\n\t}\n\n\t// end of decoding\n\treturn (int)(((char *)op) - dest);\n\n\t// write overflow error detected\n _output_error:\n\treturn (int)(-(((char *)ip) - source));\n}\n"
  },
  {
    "path": "src/lz4/lz4_format_description.txt",
    "content": "LZ4 Format Description\nLast revised: 2012-02-27\nAuthor : Y. Collet\n\n\n\nThis small specification intents to provide enough information\nto anyone willing to produce LZ4-compatible compressed streams\nusing any programming language.\n\nLZ4 is an LZ77-type compressor with a fixed, byte-oriented encoding.\nThe most important design principle behind LZ4 is simplicity.\nIt helps to create an easy to read and maintain source code.\nIt also helps later on for optimisations, compactness, and speed.\nThere is no entropy encoder backend nor framing layer.\nThe latter is assumed to be handled by other parts of the system.\n\nThis document only describes the format,\nnot how the LZ4 compressor nor decompressor actually work.\nThe correctness of the decompressor should not depend\non implementation details of the compressor, and vice versa.\n\n\n\n-- Compressed stream format --\n\nAn LZ4 compressed stream is composed of sequences.\nSchematically, a sequence is a suite of literals, followed by a match copy.\n\nEach sequence starts with a token.\nThe token is a one byte value, separated into two 4-bits fields.\nTherefore each field ranges from 0 to 15.\n\n\nThe first field uses the 4 high-bits of the token.\nIt provides the length of literals to follow.\n(Note : a literal is a not-compressed byte).\nIf the field value is 0, then there is no literal.\nIf it is 15, then we need to add some more bytes to indicate the full length.\nEach additionnal byte then represent a value from 0 to 255,\nwhich is added to the previous value to produce a total length.\nWhen the byte value is 255, another byte is output.\nThere can be any number of bytes following the token. There is no \"size limit\".\n(Sidenote this is why a not-compressible input stream is expanded by 0.4%).\n\nExample 1 : A length of 48 will be represented as :\n- 15 : value for the 4-bits High field\n- 33 : (=48-15) remaining length to reach 48\n\nExample 2 : A length of 280 will be represented as :\n- 15  : value for the 4-bits High field\n- 255 : following byte is maxed, since 280-15 >= 255\n- 10  : (=280 - 15 - 255) ) remaining length to reach 280\n\nExample 3 : A length of 15 will be represented as :\n- 15 : value for the 4-bits High field\n- 0  : (=15-15) yes, the zero must be output\n\nFollowing the token and optional length bytes, are the literals themselves.\nThey are exactly as numerous as previously decoded (length of literals).\nIt's possible that there are zero literal.\n\n\nFollowing the literals is the match copy operation.\n\nIt starts by the offset.\nThis is a 2 bytes value, in little endian format :\nthe lower byte is the first one in the stream.\n\nThe offset represents the position of the match to be copied from.\n1 means \"current position - 1 byte\".\nThe maximum offset value is 65535, 65536 cannot be coded.\nNote that 0 is an invalid value, not used.\n\nThen we need to extract the match length.\nFor this, we use the second token field, the low 4-bits.\nValue, obviously, ranges from 0 to 15.\nHowever here, 0 means that the copy operation will be minimal.\nThe minimum length of a match, called minmatch, is 4.\nAs a consequence, a 0 value means 4 bytes, and a value of 15 means 19+ bytes.\nSimilar to literal length, on reaching the highest possible value (15),\nwe output additional bytes, one at a time, with values ranging from 0 to 255.\nThey are added to total to provide the final match length.\nA 255 value means there is another byte to read and add.\nThere is no limit to the number of optional bytes that can be output this way.\n(This points towards a maximum achievable compression ratio of ~250).\n\nWith the offset and the matchlength,\nthe decoder can now proceed to copy the data from the already decoded buffer.\nOn decoding the matchlength, we reach the end of the compressed sequence,\nand therefore start another one.\n\n\n-- Parsing restrictions --\n\nThere are specific parsing rules to respect in order to remain compatible\nwith assumptions made by the decoder :\n1) The last 5 bytes are always literals\n2) The last match must start at least 12 bytes before end of stream\nConsequently, a file with less than 13 bytes cannot be compressed.\nThese rules are in place to ensure that the decoder\nwill never read beyond the input buffer, nor write beyond the output buffer.\n\nNote that the last sequence is also incomplete,\nand stops right after literals.\n\n\n-- Additional notes --\n\nThere is no assumption nor limits to the way the compressor\nsearches and selects matches within the source stream.\nIt could be a fast scan, a multi-probe, a full search using BST,\nstandard hash chains or MMC, well whatever.\n\nAdvanced parsing strategies can also be implemented, such as lazy match,\nor full optimal parsing.\n\nAll these trade-off offer distinctive speed/memory/compression advantages.\nWhatever the method used by the compressor, its result will be decodable\nby any LZ4 decoder if it follows the format specification described above.\n\n"
  },
  {
    "path": "src/lz4/lz4demo.c",
    "content": "/*\n    LZ4Demo - Demo CLI program using LZ4 compression\n    Copyright (C) Yann Collet 2011-2012\n\tGPL v2 License\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (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    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n\tYou can contact the author at :\n\t- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\n\t- LZ4 source repository : http://code.google.com/p/lz4/\n*/\n/*\n\tNote : this is *only* a demo program, an example to show how LZ4 can be used.\n\tIt is not considered part of LZ4 compression library.\n\tThe license of LZ4 is BSD.\n\tThe license of the demo program is GPL.\n*/\n\n//****************************\n// Warning messages\n//****************************\n#define _CRT_SECURE_NO_WARNINGS\t// Visual (must be first line)\n\n//****************************\n// Includes\n//****************************\n#include <stdio.h>\t\t\t\t// fprintf, fopen, fread, _fileno(?)\n#include <stdlib.h>\t\t\t\t// malloc\n#include <string.h>\t\t\t\t// strcmp\n#include <time.h>\t\t\t\t// clock\n#include <stdint.h>\t\t\t\t// uint32_t\n#ifdef _WIN32\n#    include <io.h>\t\t\t\t// _setmode\n#    include <fcntl.h>\t\t\t// _O_BINARY\n#endif\n#include \"lz4.h\"\n#include \"lz4hc.h\"\n#include \"bench.h\"\n\n//**************************************\n// Compiler functions\n//**************************************\n#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n\n#if defined(_MSC_VER)\t\t\t// Visual Studio\n#    define swap32 _byteswap_ulong\n#elif GCC_VERSION >= 430\n#    define swap32 __builtin_bswap32\n#else\nstatic inline unsigned int swap32(unsigned int x) {\n\treturn ((x << 24) & 0xff000000) | ((x << 8) & 0x00ff0000) | ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff);\n}\n#endif\n\n//****************************\n// Constants\n//****************************\n#define COMPRESSOR_NAME \"Compression CLI using LZ4 algorithm\"\n#define COMPRESSOR_VERSION \"\"\n#define COMPILED __DATE__\n#define AUTHOR \"Yann Collet\"\n#define EXTENSION \".lz4\"\n#define WELCOME_MESSAGE \"*** %s %s, by %s (%s) ***\\n\", COMPRESSOR_NAME, COMPRESSOR_VERSION, AUTHOR, COMPILED\n\nunsigned int CHUNKSIZE = 8 << 20;\t// 8 MB\n#define CACHELINE 64\n//#define ARCHIVE_MAGICNUMBER 0x184C2102\n#define ARCHIVE_MAGICNUMBER 0x50345A4C\n//#define ARCHIVE_MAGICNUMBER_SIZE 4\n#define ARCHIVE_MAGICNUMBER_SIZE 0x20\n\n//**************************************\n// Architecture Macros\n//**************************************\nstatic const int one = 1;\n#define CPU_LITTLE_ENDIAN (*(char*)(&one))\n#define CPU_BIG_ENDIAN (!CPU_LITTLE_ENDIAN)\n#define LITTLE_ENDIAN32(i)   if (CPU_BIG_ENDIAN) { i = swap32(i); }\n\n//**************************************\n// Macros\n//**************************************\n#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)\n\n//****************************\n// Functions\n//****************************\nint usage(char *exename) {\n\tDISPLAY(\"Usage :\\n\");\n\tDISPLAY(\"      %s [arg] input output\\n\", exename);\n\tDISPLAY(\"Arguments :\\n\");\n\tDISPLAY(\" -c0: Fast compression (default) \\n\");\n\tDISPLAY(\" -c1: High compression \\n\");\n\tDISPLAY(\" -d : decompression \\n\");\n\tDISPLAY(\" -b#: Benchmark files, using # compression level\\n\");\n\tDISPLAY(\" -t : check compressed file \\n\");\n\tDISPLAY(\" -h : help (this text)\\n\");\n\tDISPLAY(\"input  : can be 'stdin' (pipe) or a filename\\n\");\n\tDISPLAY(\"output : can be 'stdout'(pipe) or a filename or 'null'\\n\");\n\treturn 0;\n}\n\nint badusage(char *exename) {\n\tDISPLAY(\"Wrong parameters\\n\");\n\tusage(exename);\n\treturn 0;\n}\n\nint get_fileHandle(const char *input_filename, const char *output_filename, FILE ** pfinput, FILE ** pfoutput) {\n\tchar stdinmark[] = \"stdin\";\n\tchar stdoutmark[] = \"stdout\";\n\n\tif (!strcmp(input_filename, stdinmark)) {\n\t\tDISPLAY(\"Using stdin for input\\n\");\n\t\t*pfinput = stdin;\n#ifdef _WIN32\t\t\t\t\t// Need to set stdin/stdout to binary mode specifically for windows\n\t\t_setmode(_fileno(stdin), _O_BINARY);\n#endif\n\t} else {\n\t\t*pfinput = fopen(input_filename, \"rb\");\n\t}\n\n\tif (!strcmp(output_filename, stdoutmark)) {\n\t\tDISPLAY(\"Using stdout for output\\n\");\n\t\t*pfoutput = stdout;\n#ifdef _WIN32\t\t\t\t\t// Need to set stdin/stdout to binary mode specifically for windows\n\t\t_setmode(_fileno(stdout), _O_BINARY);\n#endif\n\t} else {\n\t\t*pfoutput = fopen(output_filename, \"wb\");\n\t}\n\n\tif (*pfinput == 0) {\n\t\tDISPLAY(\"Pb opening %s\\n\", input_filename);\n\t\treturn 2;\n\t}\n\tif (*pfoutput == 0) {\n\t\tDISPLAY(\"Pb opening %s\\n\", output_filename);\n\t\treturn 3;\n\t}\n\n\treturn 0;\n}\n\nint compress_file(char *input_filename, char *output_filename, int compressionlevel) {\n\tint (*compressionFunction) (const char *, char *, int);\n\tunsigned long long filesize = 0;\n\tunsigned long long compressedfilesize = ARCHIVE_MAGICNUMBER_SIZE;\n\tunsigned int u32var;\n\tchar *in_buff;\n\tchar *out_buff;\n\tFILE *finput;\n\tFILE *foutput;\n\tint r;\n\tint displayLevel = (compressionlevel > 0);\n\tclock_t start, end;\n\n\t// Init\n\tswitch (compressionlevel) {\n\tcase 0:\n\t\tcompressionFunction = LZ4_compress;\n\t\tbreak;\n\tcase 1:\n\t\tcompressionFunction = LZ4_compressHC;\n\t\tbreak;\n\tdefault:\n\t\tcompressionFunction = LZ4_compress;\n\t}\n\tstart = clock();\n\tr = get_fileHandle(input_filename, output_filename, &finput, &foutput);\n\tif (r)\n\t\treturn r;\n\n\t// Allocate Memory\n\n\tin_buff = (char *)malloc(CHUNKSIZE);\n\tout_buff = (char *)malloc(LZ4_compressBound(CHUNKSIZE));\n\tif (!in_buff || !out_buff) {\n\t\tDISPLAY(\"Allocation error : not enough memory\\n\");\n\t\treturn 8;\n\t}\n\t// Write Archive Header\n\tu32var = ARCHIVE_MAGICNUMBER;\n\tLITTLE_ENDIAN32(u32var);\n\t*(unsigned int *)out_buff = u32var;\n\tfwrite(out_buff, 1, ARCHIVE_MAGICNUMBER_SIZE, foutput);\n\n\t// Main Loop\n\twhile (1) {\n\t\tint outSize;\n\t\t// Read Block\n\t\tint inSize = fread(in_buff, 1, CHUNKSIZE, finput);\n\t\tif (inSize <= 0)\n\t\t\tbreak;\n\t\tfilesize += inSize;\n\t\tif (displayLevel)\n\t\t\tDISPLAY(\"Read : %i MB  \\r\", (int)(filesize >> 20));\n\n\t\t// Compress Block\n\t\toutSize = compressionFunction(in_buff, out_buff + 4, inSize);\n\t\tcompressedfilesize += outSize + 4;\n\t\tif (displayLevel)\n\t\t\tDISPLAY(\"Read : %i MB  ==> %.2f%%\\r\", (int)(filesize >> 20), (double)compressedfilesize / filesize * 100);\n\n\t\t// Write Block\n\t\tLITTLE_ENDIAN32(outSize);\n\t\t*(unsigned int *)out_buff = outSize;\n\t\tLITTLE_ENDIAN32(outSize);\n\t\tfwrite(out_buff, 1, outSize + 4, foutput);\n\t}\n\n\t// Status\n\tend = clock();\n\tDISPLAY(\"Compressed %llu bytes into %llu bytes ==> %.2f%%\\n\", (unsigned long long)filesize, (unsigned long long)compressedfilesize, (double)compressedfilesize / filesize * 100);\n\t{\n\t\tdouble seconds = (double)(end - start) / CLOCKS_PER_SEC;\n\t\tDISPLAY(\"Done in %.2f s ==> %.2f MB/s\\n\", seconds, (double)filesize / seconds / 1024 / 1024);\n\t}\n\n\t// Close & Free\n\tfree(in_buff);\n\tfree(out_buff);\n\tfclose(finput);\n\tfclose(foutput);\n\n\treturn 0;\n}\n\nint LZ4_decode_file(const char *input_filename, const char *output_filename) {\n\tunsigned long long filesize = 0;\n\tchar *in_buff;\n\tchar *out_buff;\n\tsize_t uselessRet;\n\tint sinkint;\n\tuint32_t chunkSize[ARCHIVE_MAGICNUMBER_SIZE / 4];\n\tFILE *finput;\n\tFILE *foutput;\n\tclock_t start, end;\n\tint r;\n\n\t// Init\n\tstart = clock();\n\tr = get_fileHandle(input_filename, output_filename, &finput, &foutput);\n\tif (r)\n\t\treturn r;\n\n\t// Check Archive Header\n\tuselessRet = fread(chunkSize, 1, ARCHIVE_MAGICNUMBER_SIZE, finput);\n\tif (!uselessRet) {\n\t\tDISPLAY(\"Cannot read header\\n\");\n\t\treturn -1;\n\t}\n\t//LITTLE_ENDIAN32(chunkSize);\n\tif (chunkSize[0] != ARCHIVE_MAGICNUMBER) {\n\t\tDISPLAY(\"Unrecognized header : file cannot be decoded\\n\");\n\t\treturn 6;\n\t}\n\t// Allocate Memory\n\tCHUNKSIZE = (uint32_t) chunkSize[3];\n\tin_buff = (char *)malloc(CHUNKSIZE + CHUNKSIZE / 0xFF + 64);\n\tout_buff = (char *)malloc(CHUNKSIZE);\n\tif (!in_buff || !out_buff) {\n\t\tDISPLAY(\"Allocation error : not enough memory\\n\");\n\t\treturn 7;\n\t}\n\n\tuint32_t n = 0;\n\tuint32_t nextSize;\n\tuint32_t numOfSizes = chunkSize[4];\n\tuint32_t *sizesTable = (uint32_t *) malloc(4 * numOfSizes);\n\tuselessRet = fread(sizesTable, 4, numOfSizes, finput);\n\tif (!uselessRet) {\n\t\tDISPLAY(\"Cannot read sizes table\\n\");\n\t\treturn -1;\n\t}\n\tfilesize = 0LL;\n\twhile (1) {\t\t\t\t\t// Main Loop\n\t\tnextSize = sizesTable[n];\n\t\tuselessRet = fread(in_buff, 1, nextSize, finput);\n\t\tif (!uselessRet) {\n\t\t\tDISPLAY(\"Cannot read header\\n\");\n\t\t\treturn -1;\n\t\t}\n\t\tif (n >= numOfSizes - 1) {\n\t\t\t// Decode Block\n\t\t\tsinkint = LZ4_uncompress_unknownOutputSize(in_buff, out_buff, nextSize, CHUNKSIZE);\n\t\t\tif (sinkint < 0) {\n\t\t\t\tDISPLAY(\"Decoding Failed ! Corrupted input !\\n\");\n\t\t\t\treturn 9;\n\t\t\t}\n\t\t\tfilesize += sinkint;\n\n\t\t\t// Write Block\n\t\t\tfwrite(out_buff, 1, sinkint, foutput);\n\t\t\tbreak;\n\t\t}\n\t\tuint32_t res = LZ4_uncompress(in_buff, out_buff, CHUNKSIZE);\n\t\tif (nextSize != res) {\n\t\t\tprintf(\"Uncompress error. n:%d, res:%X, nextSize:%X\\n\", n, res, nextSize);\n\t\t\treturn 8;\n\t\t}\n\t\tfilesize += CHUNKSIZE;\n\t\t++n;\n\t\tfwrite(out_buff, 1, CHUNKSIZE, foutput);\n\t\tif (n >= numOfSizes)\n\t\t\tbreak;\n\t}\n\n\t// Status\n\tend = clock();\n\tDISPLAY(\"Successfully decoded %llu bytes. \", (unsigned long long)filesize); {\n\t\tdouble seconds = (double)(end - start) / CLOCKS_PER_SEC;\n\t\tDISPLAY(\"Done in %.2f s ==> %.2f MB/s\\n\", seconds, (double)filesize / seconds / 1024 / 1024);\n\t}\n\n\t// Close & Free\n\tfree(sizesTable);\n\tfree(in_buff);\n\tfree(out_buff);\n\tfclose(finput);\n\tfclose(foutput);\n\n\treturn 0;\n}\n\n//int main(int argc, char** argv)\n//{\n  //int i,\n\t  //cLevel=0,\n\t  //decode=0,\n\t  //bench=0,\n\t  //filenamesStart=2;\n  //char* exename=argv[0];\n  //char* input_filename=0;\n  //char* output_filename=0;\n//#ifdef _WIN32\n  //char nulmark[] = \"nul\";\n//#else\n  //char nulmark[] = \"/dev/null\";\n//#endif\n  //char nullinput[] = \"null\";\n\n  // Welcome message\n  //DISPLAY( WELCOME_MESSAGE);\n\n  //if (argc<2) { badusage(exename); return 1; }\n\n  //for(i=1; i<argc; i++)\n  //{\n\t//char* argument = argv[i];\n\n\t//if(!argument) continue;   // Protection if argument empty\n\n\t// Select command\n\t//if (argument[0]=='-')\n\t//{\n\t\t//argument ++;\n\n\t\t// Display help on usage\n\t\t//if ( argument[0] =='h' ) { usage(exename); return 0; }\n\n\t\t// Compression (default)\n\t\t//if ( argument[0] =='c' ) { if (argument[1] >='0') cLevel=argument[1] - '0'; continue; }\n\n\t\t// Decoding\n\t\t//if ( argument[0] =='d' ) { decode=1; continue; }\n\n\t\t// Bench\n\t\t//if ( argument[0] =='b' ) { bench=1; if (argument[1] >= '0') cLevel=argument[1] - '0'; continue; }\n\n\t\t// Modify Block Size (benchmark only)\n\t\t//if ( argument[0] =='B' ) { int B = argument[1] - '0'; int S = 1 << (10 + 2*B); BMK_SetBlocksize(S); continue; }\n\n\t\t// Modify Nb Iterations (benchmark only)\n\t\t//if ( argument[0] =='i' ) { int iters = argument[1] - '0'; BMK_SetNbIterations(iters); continue; }\n\n\t\t// Test\n\t\t//if ( argument[0] =='t' ) { decode=1; output_filename=nulmark; continue; }\n\t//}\n\n\t// first provided filename is input\n\t//if (!input_filename) { input_filename=argument; filenamesStart=i; continue; }\n\n\t// second provided filename is output\n\t//if (!output_filename)\n\t//{\n\t\t//output_filename=argument;\n\t\t//if (!strcmp (output_filename, nullinput)) output_filename = nulmark;\n\t\t//continue;\n\t//}\n  //}\n\n  // No input filename ==> Error\n  //if(!input_filename) { badusage(exename); return 1; }\n\n  //if (bench) return BMK_benchFile(argv+filenamesStart, argc-filenamesStart, cLevel);\n\n  // No output filename ==> Error\n  //if (!output_filename) { badusage(exename); return 1; }\n\n  //if (decode) return decode_file(input_filename, output_filename);\n\n  //return compress_file(input_filename, output_filename, cLevel);   // Compression is 'default' action\n\n//}\n"
  },
  {
    "path": "src/lz4/lz4hc.c",
    "content": "/*\n   LZ4 HC - High Compression Mode of LZ4\n   Copyright (C) 2011-2012, Yann Collet.\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\n   - LZ4 source repository : http://code.google.com/p/lz4/\n*/\n\n//**************************************\n// CPU Feature Detection\n//**************************************\n// 32 or 64 bits ?\n#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) )\t// Detects 64 bits mode\n#    define LZ4_ARCH64 1\n#else\n#    define LZ4_ARCH64 0\n#endif\n\n// Little Endian or Big Endian ?\n#if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) || defined(PPC) || defined(__powerpc__) || defined(__powerpc) || defined(powerpc) || ((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) )\n#    define LZ4_BIG_ENDIAN 1\n#else\n// Little Endian assumed. PDP Endian and other very rare endian format are unsupported.\n#endif\n\n// Unaligned memory access is automatically enabled for \"common\" CPU, such as x86.\n// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected\n// If you know your target CPU supports unaligned memory access, you may want to force this option manually to improve performance\n#if defined(__ARM_FEATURE_UNALIGNED)\n#    define LZ4_FORCE_UNALIGNED_ACCESS 1\n#endif\n\n//**************************************\n// Compiler Options\n//**************************************\n#if __STDC_VERSION__ >= 199901L\t// C99\n  /* \"restrict\" is a known keyword */\n#else\n#    define restrict\t\t\t// Disable restrict\n#endif\n\n#ifdef _MSC_VER\n#    define inline __forceinline// Visual is not C99, but supports some kind of inline\n#endif\n\n#ifdef _MSC_VER\t\t\t\t\t// Visual Studio\n#    define bswap16(x) _byteswap_ushort(x)\n#else\n#    define bswap16(x)  ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8)))\n#endif\n\n//**************************************\n// Includes\n//**************************************\n#include <stdlib.h>\t\t\t\t// calloc, free\n#include <string.h>\t\t\t\t// memset, memcpy\n#include \"lz4hc.h\"\n\n#define ALLOCATOR(s) calloc(1,s)\n#define FREEMEM free\n#define MEM_INIT memset\n\n//**************************************\n// Basic Types\n//**************************************\n#if defined(_MSC_VER)\t\t\t// Visual Studio does not support 'stdint' natively\n#    define BYTE\tunsigned __int8\n#    define U16\t\tunsigned __int16\n#    define U32\t\tunsigned __int32\n#    define S32\t\t__int32\n#    define U64\t\tunsigned __int64\n#else\n#    include <stdint.h>\n#    define BYTE\tuint8_t\n#    define U16\t\tuint16_t\n#    define U32\t\tuint32_t\n#    define S32\t\tint32_t\n#    define U64\t\tuint64_t\n#endif\n\n#ifndef LZ4_FORCE_UNALIGNED_ACCESS\n#    pragma pack(push, 1)\n#endif\n\ntypedef struct _U16_S {\n\tU16 v;\n} U16_S;\ntypedef struct _U32_S {\n\tU32 v;\n} U32_S;\ntypedef struct _U64_S {\n\tU64 v;\n} U64_S;\n\n#ifndef LZ4_FORCE_UNALIGNED_ACCESS\n#    pragma pack(pop)\n#endif\n\n#define A64(x) (((U64_S *)(x))->v)\n#define A32(x) (((U32_S *)(x))->v)\n#define A16(x) (((U16_S *)(x))->v)\n\n//**************************************\n// Constants\n//**************************************\n#define MINMATCH 4\n\n#define DICTIONARY_LOGSIZE 16\n#define MAXD (1<<DICTIONARY_LOGSIZE)\n#define MAXD_MASK ((U32)(MAXD - 1))\n#define MAX_DISTANCE (MAXD - 1)\n\n#define HASH_LOG (DICTIONARY_LOGSIZE-1)\n#define HASHTABLESIZE (1 << HASH_LOG)\n#define HASH_MASK (HASHTABLESIZE - 1)\n\n#define MAX_NB_ATTEMPTS 256\n\n#define ML_BITS  4\n#define ML_MASK  (size_t)((1U<<ML_BITS)-1)\n#define RUN_BITS (8-ML_BITS)\n#define RUN_MASK ((1U<<RUN_BITS)-1)\n\n#define COPYLENGTH 8\n#define LASTLITERALS 5\n#define MFLIMIT (COPYLENGTH+MINMATCH)\n#define MINLENGTH (MFLIMIT+1)\n#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)\n\n//**************************************\n// Architecture-specific macros\n//**************************************\n#if LZ4_ARCH64\t\t\t\t\t// 64-bit\n#    define STEPSIZE 8\n#    define LZ4_COPYSTEP(s,d)\t\tA64(d) = A64(s); d+=8; s+=8;\n#    define LZ4_COPYPACKET(s,d)\t\tLZ4_COPYSTEP(s,d)\n#    define UARCH U64\n#    define AARCH A64\n#    define HTYPE\t\t\t\t\tU32\n#    define INITBASE(b,s)\t\t\tconst BYTE* const b = s\n#else // 32-bit\n#    define STEPSIZE 4\n#    define LZ4_COPYSTEP(s,d)\t\tA32(d) = A32(s); d+=4; s+=4;\n#    define LZ4_COPYPACKET(s,d)\t\tLZ4_COPYSTEP(s,d); LZ4_COPYSTEP(s,d);\n#    define UARCH U32\n#    define AARCH A32\n#    define HTYPE\t\t\t\t\tconst BYTE*\n#    define INITBASE(b,s)\t\t    const int b = 0\n#endif\n\n#if defined(LZ4_BIG_ENDIAN)\n#    define LZ4_READ_LITTLEENDIAN_16(d,s,p) { U16 v = A16(p); v = bswap16(v); d = (s) - v; }\n#    define LZ4_WRITE_LITTLEENDIAN_16(p,i)  { U16 v = (U16)(i); v = bswap16(v); A16(p) = v; p+=2; }\n#else // Little Endian\n#    define LZ4_READ_LITTLEENDIAN_16(d,s,p) { d = (s) - A16(p); }\n#    define LZ4_WRITE_LITTLEENDIAN_16(p,v)  { A16(p) = v; p+=2; }\n#endif\n\n//************************************************************\n// Local Types\n//************************************************************\ntypedef struct {\n\tconst BYTE *base;\n\tHTYPE hashTable[HASHTABLESIZE];\n\tU16 chainTable[MAXD];\n\tconst BYTE *nextToUpdate;\n} LZ4HC_Data_Structure;\n\n//**************************************\n// Macros\n//**************************************\n#define LZ4_WILDCOPY(s,d,e)\t\tdo { LZ4_COPYPACKET(s,d) } while (d<e);\n#define LZ4_BLINDCOPY(s,d,l)\t{ BYTE* e=d+l; LZ4_WILDCOPY(s,d,e); d=e; }\n#define HASH_FUNCTION(i)\t(((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))\n#define HASH_VALUE(p)\t\tHASH_FUNCTION(*(U32*)(p))\n#define HASH_POINTER(p)\t\t(HashTable[HASH_VALUE(p)] + base)\n#define DELTANEXT(p)\t\tchainTable[(size_t)(p) & MAXD_MASK]\n#define GETNEXT(p)\t\t\t((p) - (size_t)DELTANEXT(p))\n#define ADD_HASH(p)\t\t\t{ size_t delta = (p) - HASH_POINTER(p); if (delta>MAX_DISTANCE) delta = MAX_DISTANCE; DELTANEXT(p) = (U16)delta; HashTable[HASH_VALUE(p)] = (p) - base; }\n\n//**************************************\n// Private functions\n//**************************************\n#if LZ4_ARCH64\n\ninline static int LZ4_NbCommonBytes(register U64 val) {\n#    if defined(LZ4_BIG_ENDIAN)\n#        if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\tunsigned long r = 0;\n\t_BitScanReverse64(&r, val);\n\treturn (int)(r >> 3);\n#        elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\treturn (__builtin_clzll(val) >> 3);\n#        else\n\tint r;\n\tif (!(val >> 32)) {\n\t\tr = 4;\n\t} else {\n\t\tr = 0;\n\t\tval >>= 32;\n\t}\n\tif (!(val >> 16)) {\n\t\tr += 2;\n\t\tval >>= 8;\n\t} else {\n\t\tval >>= 24;\n\t}\n\tr += (!val);\n\treturn r;\n#        endif\n#    else\n#        if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\tunsigned long r = 0;\n\t_BitScanForward64(&r, val);\n\treturn (int)(r >> 3);\n#        elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\treturn (__builtin_ctzll(val) >> 3);\n#        else\n\tstatic const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };\n\treturn DeBruijnBytePos[((U64) ((val & -val) * 0x0218A392CDABBD3F)) >> 58];\n#        endif\n#    endif\n}\n\n#else\n\ninline static int LZ4_NbCommonBytes(register U32 val) {\n#    if defined(LZ4_BIG_ENDIAN)\n#        if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\tunsigned long r = 0;\n\t_BitScanReverse(&r, val);\n\treturn (int)(r >> 3);\n#        elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\treturn (__builtin_clz(val) >> 3);\n#        else\n\tint r;\n\tif (!(val >> 16)) {\n\t\tr = 2;\n\t\tval >>= 8;\n\t} else {\n\t\tr = 0;\n\t\tval >>= 24;\n\t}\n\tr += (!val);\n\treturn r;\n#        endif\n#    else\n#        if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\tunsigned long r = 0;\n\t_BitScanForward(&r, val);\n\treturn (int)(r >> 3);\n#        elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\n\treturn (__builtin_ctz(val) >> 3);\n#        else\n\tstatic const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };\n\treturn DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27];\n#        endif\n#    endif\n}\n\n#endif\n\ninline static int LZ4HC_Init(LZ4HC_Data_Structure * hc4, const BYTE * base) {\n\tMEM_INIT((void *)hc4->hashTable, 0, sizeof(hc4->hashTable));\n\tMEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));\n\thc4->nextToUpdate = base + LZ4_ARCH64;\n\thc4->base = base;\n\treturn 1;\n}\n\ninline static void *LZ4HC_Create(const BYTE * base) {\n\tvoid *hc4 = ALLOCATOR(sizeof(LZ4HC_Data_Structure));\n\n\tLZ4HC_Init(hc4, base);\n\treturn hc4;\n}\n\ninline static int LZ4HC_Free(void **LZ4HC_Data) {\n\tFREEMEM(*LZ4HC_Data);\n\t*LZ4HC_Data = NULL;\n\treturn (1);\n}\n\ninline static void LZ4HC_Insert(LZ4HC_Data_Structure * hc4, const BYTE * ip) {\n\tU16 *chainTable = hc4->chainTable;\n\tHTYPE *HashTable = hc4->hashTable;\n\tINITBASE(base, hc4->base);\n\n\twhile (hc4->nextToUpdate < ip) {\n\t\tADD_HASH(hc4->nextToUpdate);\n\t\thc4->nextToUpdate++;\n\t}\n}\n\ninline static int LZ4HC_InsertAndFindBestMatch(LZ4HC_Data_Structure * hc4, const BYTE * ip, const BYTE * const matchlimit, const BYTE ** matchpos) {\n\tU16 *const chainTable = hc4->chainTable;\n\tHTYPE *const HashTable = hc4->hashTable;\n\tconst BYTE *ref;\n\tINITBASE(base, hc4->base);\n\tint nbAttempts = MAX_NB_ATTEMPTS;\n\tint ml = 0;\n\n\t// HC4 match finder\n\tLZ4HC_Insert(hc4, ip);\n\tref = HASH_POINTER(ip);\n\twhile ((ref > (ip - MAX_DISTANCE)) && (nbAttempts)) {\n\t\tnbAttempts--;\n\t\tif (*(ref + ml) == *(ip + ml))\n\t\t\tif (*(U32 *) ref == *(U32 *) ip) {\n\t\t\t\tconst BYTE *reft = ref + MINMATCH;\n\t\t\t\tconst BYTE *ipt = ip + MINMATCH;\n\n\t\t\t\twhile (ipt < matchlimit - (STEPSIZE - 1)) {\n\t\t\t\t\tUARCH diff = AARCH(reft) ^ AARCH(ipt);\n\t\t\t\t\tif (!diff) {\n\t\t\t\t\t\tipt += STEPSIZE;\n\t\t\t\t\t\treft += STEPSIZE;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tipt += LZ4_NbCommonBytes(diff);\n\t\t\t\t\tgoto _endCount;\n\t\t\t\t}\n\t\t\t\tif (LZ4_ARCH64)\n\t\t\t\t\tif ((ipt < (matchlimit - 3)) && (A32(reft) == A32(ipt))) {\n\t\t\t\t\t\tipt += 4;\n\t\t\t\t\t\treft += 4;\n\t\t\t\t\t}\n\t\t\t\tif ((ipt < (matchlimit - 1)) && (A16(reft) == A16(ipt))) {\n\t\t\t\t\tipt += 2;\n\t\t\t\t\treft += 2;\n\t\t\t\t}\n\t\t\t\tif ((ipt < matchlimit) && (*reft == *ipt))\n\t\t\t\t\tipt++;\n _endCount:\n\n\t\t\t\tif (ipt - ip > ml) {\n\t\t\t\t\tml = ipt - ip;\n\t\t\t\t\t*matchpos = ref;\n\t\t\t\t}\n\t\t\t}\n\t\tref = GETNEXT(ref);\n\t}\n\n\treturn ml;\n}\n\ninline static int LZ4HC_InsertAndGetWiderMatch(LZ4HC_Data_Structure * hc4, const BYTE * ip, const BYTE * startLimit, const BYTE * matchlimit, int longest, const BYTE ** matchpos, const BYTE ** startpos) {\n\tU16 *const chainTable = hc4->chainTable;\n\tHTYPE *const HashTable = hc4->hashTable;\n\tINITBASE(base, hc4->base);\n\tconst BYTE *ref;\n\tint nbAttempts = MAX_NB_ATTEMPTS;\n\tint delta = ip - startLimit;\n\n\t// First Match\n\tLZ4HC_Insert(hc4, ip);\n\tref = HASH_POINTER(ip);\n\n\twhile ((ref > ip - MAX_DISTANCE) && (ref >= hc4->base) && (nbAttempts)) {\n\t\tnbAttempts--;\n\t\tif (*(startLimit + longest) == *(ref - delta + longest))\n\t\t\tif (*(U32 *) ref == *(U32 *) ip) {\n\t\t\t\tconst BYTE *reft = ref + MINMATCH;\n\t\t\t\tconst BYTE *ipt = ip + MINMATCH;\n\t\t\t\tconst BYTE *startt = ip;\n\n\t\t\t\twhile (ipt < matchlimit - (STEPSIZE - 1)) {\n\t\t\t\t\tUARCH diff = AARCH(reft) ^ AARCH(ipt);\n\t\t\t\t\tif (!diff) {\n\t\t\t\t\t\tipt += STEPSIZE;\n\t\t\t\t\t\treft += STEPSIZE;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tipt += LZ4_NbCommonBytes(diff);\n\t\t\t\t\tgoto _endCount;\n\t\t\t\t}\n\t\t\t\tif (LZ4_ARCH64)\n\t\t\t\t\tif ((ipt < (matchlimit - 3)) && (A32(reft) == A32(ipt))) {\n\t\t\t\t\t\tipt += 4;\n\t\t\t\t\t\treft += 4;\n\t\t\t\t\t}\n\t\t\t\tif ((ipt < (matchlimit - 1)) && (A16(reft) == A16(ipt))) {\n\t\t\t\t\tipt += 2;\n\t\t\t\t\treft += 2;\n\t\t\t\t}\n\t\t\t\tif ((ipt < matchlimit) && (*reft == *ipt))\n\t\t\t\t\tipt++;\n _endCount:\n\n\t\t\t\treft = ref;\n\t\t\t\twhile ((startt > startLimit) && (reft > hc4->base) && (startt[-1] == reft[-1])) {\n\t\t\t\t\tstartt--;\n\t\t\t\t\treft--;\n\t\t\t\t}\n\n\t\t\t\tif ((ipt - startt) > longest) {\n\t\t\t\t\tlongest = ipt - startt;\n\t\t\t\t\t*matchpos = reft;\n\t\t\t\t\t*startpos = startt;\n\t\t\t\t}\n\t\t\t}\n\t\tref = GETNEXT(ref);\n\t}\n\n\treturn longest;\n}\n\ninline static int LZ4_encodeSequence(const BYTE ** ip, BYTE ** op, const BYTE ** anchor, int ml, const BYTE * ref) {\n\tint length, len;\n\tBYTE *token;\n\n\t// Encode Literal length\n\tlength = *ip - *anchor;\n\ttoken = (*op)++;\n\tif (length >= (int)RUN_MASK) {\n\t\t*token = (RUN_MASK << ML_BITS);\n\t\tlen = length - RUN_MASK;\n\t\tfor (; len > 254; len -= 255)\n\t\t\t*(*op)++ = 255;\n\t\t*(*op)++ = (BYTE) len;\n\t} else\n\t\t*token = (length << ML_BITS);\n\n\t// Copy Literals\n\tLZ4_BLINDCOPY(*anchor, *op, length);\n\n\t// Encode Offset\n\tLZ4_WRITE_LITTLEENDIAN_16(*op, *ip - ref);\n\n\t// Encode MatchLength\n\tlen = (int)(ml - MINMATCH);\n\tif (len >= (int)ML_MASK) {\n\t\t*token += ML_MASK;\n\t\tlen -= ML_MASK;\n\t\tfor (; len > 509; len -= 510) {\n\t\t\t*(*op)++ = 255;\n\t\t\t*(*op)++ = 255;\n\t\t}\n\t\tif (len > 254) {\n\t\t\tlen -= 255;\n\t\t\t*(*op)++ = 255;\n\t\t}\n\t\t*(*op)++ = (BYTE) len;\n\t} else\n\t\t*token += len;\n\n\t// Prepare next loop\n\t*ip += ml;\n\t*anchor = *ip;\n\n\treturn 0;\n}\n\n//****************************\n// Compression CODE\n//****************************\n\nint LZ4_compressHCCtx(LZ4HC_Data_Structure * ctx, const char *source, char *dest, int isize) {\n\tconst BYTE *ip = (const BYTE *)source;\n\tconst BYTE *anchor = ip;\n\tconst BYTE *const iend = ip + isize;\n\tconst BYTE *const mflimit = iend - MFLIMIT;\n\tconst BYTE *const matchlimit = (iend - LASTLITERALS);\n\n\tBYTE *op = (BYTE *) dest;\n\n\tint ml, ml2, ml3, ml0;\n\tconst BYTE *ref = NULL;\n\tconst BYTE *start2 = NULL;\n\tconst BYTE *ref2 = NULL;\n\tconst BYTE *start3 = NULL;\n\tconst BYTE *ref3 = NULL;\n\tconst BYTE *start0;\n\tconst BYTE *ref0;\n\n\tip++;\n\n\t// Main Loop\n\twhile (ip < mflimit) {\n\t\tml = LZ4HC_InsertAndFindBestMatch(ctx, ip, matchlimit, (&ref));\n\t\tif (!ml) {\n\t\t\tip++;\n\t\t\tcontinue;\n\t\t}\n\t\t// saved, in case we would skip too much\n\t\tstart0 = ip;\n\t\tref0 = ref;\n\t\tml0 = ml;\n\n _Search2:\n\t\tif (ip + ml < mflimit)\n\t\t\tml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2);\n\t\telse\n\t\t\tml2 = ml;\n\n\t\tif (ml2 == ml)\t\t\t// No better match\n\t\t{\n\t\t\tLZ4_encodeSequence(&ip, &op, &anchor, ml, ref);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (start0 < ip) {\n\t\t\tif (start2 < ip + ml0)\t// empirical\n\t\t\t{\n\t\t\t\tip = start0;\n\t\t\t\tref = ref0;\n\t\t\t\tml = ml0;\n\t\t\t}\n\t\t}\n\t\t// Here, start0==ip\n\t\tif ((start2 - ip) < 3)\t// First Match too small : removed\n\t\t{\n\t\t\tml = ml2;\n\t\t\tip = start2;\n\t\t\tref = ref2;\n\t\t\tgoto _Search2;\n\t\t}\n\n _Search3:\n\t\t// Currently we have :\n\t\t// ml2 > ml1, and\n\t\t// ip1+3 <= ip2 (usually < ip1+ml1)\n\t\tif ((start2 - ip) < OPTIMAL_ML) {\n\t\t\tint correction;\n\t\t\tint new_ml = ml;\n\t\t\tif (new_ml > OPTIMAL_ML)\n\t\t\t\tnew_ml = OPTIMAL_ML;\n\t\t\tif (ip + new_ml > start2 + ml2 - MINMATCH)\n\t\t\t\tnew_ml = start2 - ip + ml2 - MINMATCH;\n\t\t\tcorrection = new_ml - (start2 - ip);\n\t\t\tif (correction > 0) {\n\t\t\t\tstart2 += correction;\n\t\t\t\tref2 += correction;\n\t\t\t\tml2 -= correction;\n\t\t\t}\n\t\t}\n\t\t// Now, we have start2 = ip+new_ml, with new_ml=min(ml, OPTIMAL_ML=18)\n\n\t\tif (start2 + ml2 < mflimit)\n\t\t\tml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3);\n\t\telse\n\t\t\tml3 = ml2;\n\n\t\tif (ml3 == ml2)\t\t\t// No better match : 2 sequences to encode\n\t\t{\n\t\t\t// ip & ref are known; Now for ml\n\t\t\tif (start2 < ip + ml) {\n\t\t\t\tif ((start2 - ip) < OPTIMAL_ML) {\n\t\t\t\t\tint correction;\n\t\t\t\t\tif (ml > OPTIMAL_ML)\n\t\t\t\t\t\tml = OPTIMAL_ML;\n\t\t\t\t\tif (ip + ml > start2 + ml2 - MINMATCH)\n\t\t\t\t\t\tml = start2 - ip + ml2 - MINMATCH;\n\t\t\t\t\tcorrection = ml - (start2 - ip);\n\t\t\t\t\tif (correction > 0) {\n\t\t\t\t\t\tstart2 += correction;\n\t\t\t\t\t\tref2 += correction;\n\t\t\t\t\t\tml2 -= correction;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tml = start2 - ip;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Now, encode 2 sequences\n\t\t\tLZ4_encodeSequence(&ip, &op, &anchor, ml, ref);\n\t\t\tip = start2;\n\t\t\tLZ4_encodeSequence(&ip, &op, &anchor, ml2, ref2);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (start3 < ip + ml + 3)\t// Not enough space for match 2 : remove it\n\t\t{\n\t\t\tif (start3 >= (ip + ml))\t// can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1\n\t\t\t{\n\t\t\t\tif (start2 < ip + ml) {\n\t\t\t\t\tint correction = (ip + ml) - start2;\n\t\t\t\t\tstart2 += correction;\n\t\t\t\t\tref2 += correction;\n\t\t\t\t\tml2 -= correction;\n\t\t\t\t\tif (ml2 < MINMATCH) {\n\t\t\t\t\t\tstart2 = start3;\n\t\t\t\t\t\tref2 = ref3;\n\t\t\t\t\t\tml2 = ml3;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tLZ4_encodeSequence(&ip, &op, &anchor, ml, ref);\n\t\t\t\tip = start3;\n\t\t\t\tref = ref3;\n\t\t\t\tml = ml3;\n\n\t\t\t\tstart0 = start2;\n\t\t\t\tref0 = ref2;\n\t\t\t\tml0 = ml2;\n\t\t\t\tgoto _Search2;\n\t\t\t}\n\n\t\t\tstart2 = start3;\n\t\t\tref2 = ref3;\n\t\t\tml2 = ml3;\n\t\t\tgoto _Search3;\n\t\t}\n\t\t// OK, now we have 3 ascending matches; let's write at least the first one\n\t\t// ip & ref are known; Now for ml\n\t\tif (start2 < ip + ml) {\n\t\t\tif ((start2 - ip) < (int)ML_MASK) {\n\t\t\t\tint correction;\n\t\t\t\tif (ml > OPTIMAL_ML)\n\t\t\t\t\tml = OPTIMAL_ML;\n\t\t\t\tif (ip + ml > start2 + ml2 - MINMATCH)\n\t\t\t\t\tml = start2 - ip + ml2 - MINMATCH;\n\t\t\t\tcorrection = ml - (start2 - ip);\n\t\t\t\tif (correction > 0) {\n\t\t\t\t\tstart2 += correction;\n\t\t\t\t\tref2 += correction;\n\t\t\t\t\tml2 -= correction;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tml = start2 - ip;\n\t\t\t}\n\t\t}\n\t\tLZ4_encodeSequence(&ip, &op, &anchor, ml, ref);\n\n\t\tip = start2;\n\t\tref = ref2;\n\t\tml = ml2;\n\n\t\tstart2 = start3;\n\t\tref2 = ref3;\n\t\tml2 = ml3;\n\n\t\tgoto _Search3;\n\n\t}\n\n\t// Encode Last Literals\n\t{\n\t\tint lastRun = iend - anchor;\n\t\tif (lastRun >= (int)RUN_MASK) {\n\t\t\t*op++ = (RUN_MASK << ML_BITS);\n\t\t\tlastRun -= RUN_MASK;\n\t\t\tfor (; lastRun > 254; lastRun -= 255)\n\t\t\t\t*op++ = 255;\n\t\t\t*op++ = (BYTE) lastRun;\n\t\t} else\n\t\t\t*op++ = (lastRun << ML_BITS);\n\t\tmemcpy(op, anchor, iend - anchor);\n\t\top += iend - anchor;\n\t}\n\n\t// End\n\treturn (int)(((char *)op) - dest);\n}\n\nint LZ4_compressHC(const char *source, char *dest, int isize) {\n\tvoid *ctx = LZ4HC_Create((const BYTE *)source);\n\tint result = LZ4_compressHCCtx(ctx, source, dest, isize);\n\tLZ4HC_Free(&ctx);\n\n\treturn result;\n}\n"
  },
  {
    "path": "src/lzhs/CMakeLists.txt",
    "content": "add_library(lzhs lzhs.c lzhs_lib.c)\ntarget_link_libraries(lzhs utils)\n"
  },
  {
    "path": "src/lzhs/lzhs.c",
    "content": "/**\n * LZHS Encoder\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * All right reserved\n */\n/**************************************************************\n        LZSS.C -- A Data Compression Program\n        (tab = 4 spaces)\n***************************************************************\n        4/6/1989 Haruhiko Okumura\n        Use, distribute, and modify this program freely.\n        Please send me your improved versions.\n                PC-VAN          SCIENCE\n                NIFTY-Serve     PAF01022\n                CompuServe      74050,1022\n**************************************************************/\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include \"common.h\"\n#include \"util.h\"\n#include \"lzhs/lzhs.h\"\n#include \"lzhs/tables.h\"\n\n/*** Huffman decoding tables ***/\nstatic t_code(*huff_charlen)[1] = (void *)&charlen_table;\t// Raw LZSS Characters + Length of LZSS match\nstatic t_code(*huff_pos)[1] = (void *)&pos_table;\t\t// Position of LZSS match\n\n/*** Huffman lookup tables ***/\n// indices 0-287 for charlen, 0-31 for charpos\n// signed -1 is used as the invalid/unpopulated index\nstatic int16_t lookup_charlen[131072];\t//2^(13 + 4 bits for key_charlen)\nstatic int16_t lookup_charpos[512];\t\t//2^( 6 + 3 bits for key_charpos)\n\n/*\n * Pack together length and code to create a key for the lookup table\n * [length][code]\n */\nstatic inline uint32_t key_charlen(uint32_t code, uint32_t len){\n\treturn ((len & 0xF) << 13) | (code & 0x1FFF);\n}\nstatic inline uint16_t key_charpos(uint32_t code, uint32_t len){\n\treturn ((len & 0x7) << 6) | (code & 0x3F);\n}\n\n\nvoid lzhs_init_lookup(){\n\tmemset(&lookup_charlen, 0xFF, sizeof(lookup_charlen));\n\tmemset(&lookup_charpos, 0xFF, sizeof(lookup_charpos));\n}\n\nstruct lzhs_ctx *lzhs_ctx_new(){\n\tstruct lzhs_ctx *ctx = calloc(1, sizeof(struct lzhs_ctx));\n\tctx->bitno = 8;\n\treturn ctx;\n}\n\n///////////// LZSS ALGO /////////////\nstatic void InitTree(struct lzhs_ctx *ctx) {\n\tint i;\n\tfor (i = N + 1; i <= N + 256; i++)\n\t\tctx->rson[i] = N;\n\tfor (i = 0; i < N; i++)\n\t\tctx->dad[i] = N;\n}\n\nstatic void lazy_match(struct lzhs_ctx *ctx, int r) {\n\tunsigned char *key;\n\tint i, p, cmp = 1, tmp = 0;\n\n\tif (ctx->match_length <= F - THRESHOLD) {\n\t\tkey = &ctx->text_buf[r + 1];\n\t\tp = key[0] + N + 1;\n\t\twhile (1) {\n\t\t\tif (cmp >= 0) {\n\t\t\t\tif (ctx->rson[p] != N)\n\t\t\t\t\tp = ctx->rson[p];\n\t\t\t\telse\n\t\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tif (ctx->lson[p] != N)\n\t\t\t\t\tp = ctx->lson[p];\n\t\t\t\telse\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfor (i = 1; i <= F - 1; i++) {\n\t\t\t\tcmp = key[i] - ctx->text_buf[p + i];\n\t\t\t\tif (key[i] != ctx->text_buf[p + i])\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (i > tmp)\n\t\t\t\tif ((tmp = i) > F - 1)\n\t\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (tmp > ctx->match_length)\n\t\tctx->match_length = 0;\n}\n\nstatic void InsertNode(struct lzhs_ctx *ctx, int r) {\n\tunsigned char *key = &ctx->text_buf[r];\n\tint tmp, p, i, cmp = 1;\n\n\tp = ctx->text_buf[r] + N + 1;\n\tctx->lson[r] = ctx->rson[r] = N;\n\n\tctx->match_length = 0;\n\twhile (1) {\n\t\tif (cmp < 0) {\n\t\t\tif (ctx->lson[p] == N) {\n\t\t\t\tctx->lson[p] = r;\n\t\t\t\tctx->dad[r] = p;\n\t\t\t\treturn lazy_match(ctx, r);\n\t\t\t}\n\t\t\tp = ctx->lson[p];\n\t\t} else {\n\t\t\tif (ctx->rson[p] == N) {\n\t\t\t\tctx->rson[p] = r;\n\t\t\t\tctx->dad[r] = p;\n\t\t\t\treturn lazy_match(ctx, r);\n\t\t\t}\n\t\t\tp = ctx->rson[p];\n\t\t}\n\t\tfor (i = 1;; ++i) {\n\t\t\tif (i < F) {\n\t\t\t\tcmp = key[i] - ctx->text_buf[p + i];\n\t\t\t\tif (key[i] == ctx->text_buf[p + i])\n\t\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tif (i >= ctx->match_length) {\n\t\t\tif (r < p)\n\t\t\t\ttmp = r - p + N;\n\t\t\telse\n\t\t\t\ttmp = r - p;\n\t\t}\n\t\tif (i >= ctx->match_length) {\n\t\t\tif (i == ctx->match_length) {\n\t\t\t\tif (tmp < ctx->match_position)\n\t\t\t\t\tctx->match_position = tmp;\n\t\t\t} else\n\t\t\t\tctx->match_position = tmp;\n\t\t\tif ((ctx->match_length = i) > F - 1)\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tctx->dad[r] = ctx->dad[p];\n\tctx->lson[r] = ctx->lson[p];\n\tctx->rson[r] = ctx->rson[p];\n\tctx->dad[ctx->lson[p]] = ctx->dad[ctx->rson[p]] = r;\n\tif (ctx->rson[ctx->dad[p]] == p)\n\t\tctx->rson[ctx->dad[p]] = r;\n\telse\n\t\tctx->lson[ctx->dad[p]] = r;\n\tctx->dad[p] = N;\n}\n\nstatic void DeleteNode(struct lzhs_ctx *ctx, int p) {\n\tint q;\n\tif (ctx->dad[p] == N)\n\t\treturn;\n\tif (ctx->rson[p] == N)\n\t\tq = ctx->lson[p];\n\telse if (ctx->lson[p] == N)\n\t\tq = ctx->rson[p];\n\telse {\n\t\tq = ctx->lson[p];\n\t\tif (ctx->rson[q] != N) {\n\t\t\tdo {\n\t\t\t\tq = ctx->rson[q];\n\t\t\t} while (ctx->rson[q] != N);\n\t\t\tctx->rson[ctx->dad[q]] = ctx->lson[q];\n\t\t\tctx->dad[ctx->lson[q]] = ctx->dad[q];\n\t\t\tctx->lson[q] = ctx->lson[p];\n\t\t\tctx->dad[ctx->lson[p]] = q;\n\t\t}\n\t\tctx->rson[q] = ctx->rson[p];\n\t\tctx->dad[ctx->rson[p]] = q;\n\t}\n\tctx->dad[q] = ctx->dad[p];\n\tif (ctx->rson[ctx->dad[p]] == p)\n\t\tctx->rson[ctx->dad[p]] = q;\n\telse\n\t\tctx->lson[ctx->dad[p]] = q;\n\tctx->dad[p] = N;\n}\n\n///////////// HUFFMAN ALGO /////////////\nstatic void InitHuffman(struct lzhs_ctx *ctx) {\n\tctx->code = ctx->len = 0;\n\tctx->preno = ctx->precode = 0;\n\t// Clear the huffman code buffer\n\tmemset(&ctx->code_buf, 0x00, sizeof(ctx->code_buf));\n\t// Initial bit no (to fetch next byte at first iteration)\n\tctx->bitno = 8;\n}\n\nstatic void putChar(struct lzhs_ctx *ctx, uint32_t code, uint32_t no, FILE *out) {\n\tuint32_t tmpno, tmpcode;\n\tif (ctx->preno + no > 7) {\n\t\tdo {\n\t\t\tno -= tmpno = 8 - ctx->preno;\n\t\t\ttmpcode = ctx->code >> no;\n\t\t\tfputc(tmpcode | (ctx->precode << tmpno), out);\n\t\t\tctx->code -= tmpcode << no;\n\t\t\tctx->preno = ctx->precode = 0;\n\t\t} while (no > 7);\n\t\tctx->preno = no;\n\t\tctx->precode = code;\n\t} else {\n\t\tctx->preno += no;\n\t\tctx->precode = code | (ctx->precode << no);\n\t}\n}\n\nstatic inline int getData(struct lzhs_ctx *ctx, cursor_t *in) {\n\tif (ctx->bitno > 7) {\n\t\tctx->bitno = 0;\n\t\tif((ctx->c = cgetc(in)) == EOF){\n\t\t\treturn 0;\n\t\t}\n\t}\n\tctx->code = (ctx->code << 1) | ((ctx->c >> (7 - ctx->bitno++)) & 1);\t// get bit msb - index\n\tctx->len++;\n\treturn 1;\n}\n\n///////////// EXPORTS /////////////\n\n/*\n * Huffman encodes the specified stream\n */\nvoid huff(struct lzhs_ctx *ctx, FILE * in, FILE * out, unsigned long int *p_textsize, unsigned long int *p_codesize) {\n\tctx->textsize = ctx->codesize;\n\tctx->codesize = 0;\n\tint c, i, j, m, flags = 0;\n\twhile (1) {\n\t\tif (((flags >>= 1) & 256) == 0) {\n\t\t\tif ((c = getc(in)) == EOF)\n\t\t\t\tbreak;\n\t\t\tflags = c | 0xFF00;\n\t\t}\n\t\tif (flags & 1) {\n\t\t\tif ((c = getc(in)) == EOF)\n\t\t\t\tbreak;\n\t\t\tputChar(ctx, huff_charlen[c]->code, huff_charlen[c]->len, out);\t// lookup in char table\n\t\t} else {\n\t\t\tif ((j = getc(in)) == EOF)\n\t\t\t\tbreak;\t\t\t// match length\n\t\t\tif ((i = getc(in)) == EOF)\n\t\t\t\tbreak;\t\t\t// byte1 of match position\n\t\t\tif ((m = getc(in)) == EOF)\n\t\t\t\tbreak;\t\t\t// byte0 of match position\n\t\t\tputChar(ctx, huff_charlen[256 + j]->code, huff_charlen[256 + j]->len, out);\t// lookup in len table\n\t\t\ti = m | (i << 8);\n\t\t\tputChar(ctx, huff_pos[(i >> 7)]->code, huff_pos[(i >> 7)]->len, out);\t// lookup in pos table\n\t\t\tputChar(ctx, i - (i >> 7 << 7), 7, out);\n\t\t}\n\t}\n\tputc(ctx->precode << (8 - ctx->preno), out);\n\tctx->codesize = ftell(out) - sizeof(struct lzhs_header);\n\tif(p_textsize)\n\t\t*p_textsize = ctx->textsize;\n\tif(p_codesize)\n\t\t*p_codesize = ctx->codesize;\n\tprintf(\"LZHS Out(%ld)/In(%ld): %.4f\\n\", ctx->codesize, ctx->textsize, (double)ctx->codesize / ctx->textsize);\n}\n\n/*\n * Huffman decodes the specified stream\n */\nvoid unhuff(struct lzhs_ctx *ctx, cursor_t *in, cursor_t *out) {\n\tInitHuffman(ctx);\n\tctx->code_buf[0] = 0;\n\tctx->code_buf_ptr = ctx->mask = 1;\n\n\twhile (1) {\n\t\tif (UNLIKELY(!getData(ctx, in)))\n\t\t\tgoto flush_ret;\n\t\tif (ctx->len < 4)\n\t\t\tcontinue; // len in code_len table should be min 4\n\t\tuint32_t key = key_charlen(ctx->code, ctx->len);\n\t\tctx->i = lookup_charlen[key];\n\t\tif(ctx->i == -2) continue;\n\t\tif(ctx->i == -1){\n\t\t\tbool found = false;\n\t\t\tfor (ctx->i = 0; ctx->i < 288; ctx->i++) {\n\t\t\t\tif (huff_charlen[ctx->i]->len == ctx->len &&\n\t\t\t\t\thuff_charlen[ctx->i]->code == ctx->code\n\t\t\t\t){\n\t\t\t\t\tlookup_charlen[key] = ctx->i;\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(!found){\n\t\t\t\tlookup_charlen[key] = -2;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif(ctx->i > 255){\n\t\t\tctx->code_buf[ctx->code_buf_ptr++] = ctx->i - 256;\n\t\t\tctx->code = ctx->len = 0;\n\t\t\twhile (1) {\n\t\t\t\tif (UNLIKELY(!getData(ctx, in)))\n\t\t\t\t\tgoto flush_ret;\n\t\t\t\tif (ctx->len < 2)\n\t\t\t\t\tcontinue;\t// len in pos table should be min 2\n\t\t\t\tuint32_t key = key_charpos(ctx->code, ctx->len);\n\t\t\t\tctx->j = lookup_charpos[key];\n\t\t\t\tif(ctx->j == -2) continue;\n\t\t\t\tif(ctx->j == -1){\n\t\t\t\t\tbool found = false;\n\t\t\t\t\tfor (ctx->j = 0; ctx->j < 32; ctx->j++) {\n\t\t\t\t\t\tif (huff_pos[ctx->j]->len == ctx->len &&\n\t\t\t\t\t\t\thuff_pos[ctx->j]->code == ctx->code\n\t\t\t\t\t\t){\n\t\t\t\t\t\t\tlookup_charpos[key] = ctx->j;\n\t\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(!found){\n\t\t\t\t\t\tlookup_charpos[key] = -2;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tctx->code_buf[ctx->code_buf_ptr++] = ctx->j >> 1;\n\t\t\t\tctx->k = -1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tctx->code = 0;\n\t\t\tfor (ctx->k = 0; ctx->k < 7; ctx->k++)\n\t\t\t\tif (UNLIKELY(!getData(ctx, in)))\n\t\t\t\t\tgoto flush_ret;\n\t\t\tctx->code_buf[ctx->code_buf_ptr++] = ctx->code | (ctx->j << 7);\n\t\t\tctx->code = ctx->len = 0;\n\t\t} else {\n\t\t\tctx->code_buf[0] |= ctx->mask;\n\t\t\tctx->code_buf[ctx->code_buf_ptr++] = ctx->i;\n\t\t\tctx->code = ctx->len = 0;\n\t\t}\n\t\tif ((ctx->mask <<= 1) == 0) {\n\t\t\tfor (ctx->j = 0; ctx->j < ctx->code_buf_ptr; ctx->j++){\n\t\t\t\tif(UNLIKELY(cputc(ctx->code_buf[ctx->j], out) == EOF))\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tctx->code_buf[0] = 0;\n\t\t\tctx->code_buf_ptr = ctx->mask = 1;\n\t\t}\n\t}\n\n\tflush_ret:\n\tif (ctx->code_buf_ptr > 1)\t// flushing buffer\n\t\tfor (ctx->i = 0; ctx->i < ctx->code_buf_ptr; ctx->i++){\n\t\t\tif(UNLIKELY(cputc(ctx->code_buf[ctx->i], out) == EOF))\n\t\t\t\treturn;\n\t\t}\n\treturn;\n}\n\n/*\n * LZSS encodes the specified stream\n */\nvoid lzss(struct lzhs_ctx *ctx, FILE * infile, FILE * outfile, unsigned long int *p_textsize, unsigned long int *p_codesize) {\n\tint c, i, len, r, s, last_match_length, code_buf_ptr;\n\tunsigned char code_buf[32], mask;\n\n\tInitTree(ctx);\n\tcode_buf[0] = 0;\n\tcode_buf_ptr = mask = 1;\n\ts = ctx->codesize = 0;\n\tr = N - F;\n\n\tfor (len = 0; len < F && (c = getc(infile)) != EOF; len++)\n\t\tctx->text_buf[r + len] = c;\n\tif ((ctx->textsize = len) == 0)\n\t\treturn;\n\n\tInsertNode(ctx, r);\n\tdo {\n\t\tif (ctx->match_length > len)\n\t\t\tctx->match_length = len;\n\t\tif (ctx->match_length <= THRESHOLD) {\n\t\t\tctx->match_length = 1;\n\t\t\tcode_buf[0] |= mask;\n\t\t\tcode_buf[code_buf_ptr++] = ctx->text_buf[r];\n\t\t} else {\n\t\t\tcode_buf[code_buf_ptr++] = ctx->match_length - THRESHOLD - 1;\n\t\t\tcode_buf[code_buf_ptr++] = (ctx->match_position >> 8) & 0xff;\n\t\t\tcode_buf[code_buf_ptr++] = ctx->match_position;\n\t\t}\n\t\tif ((mask <<= 1) == 0) {\n\t\t\tfor (i = 0; i < code_buf_ptr; i++) {\n\t\t\t\tputc(code_buf[i], outfile);\n\t\t\t\tctx->codesize++;\n\t\t\t}\n\t\t\tcode_buf[0] = 0;\n\t\t\tcode_buf_ptr = mask = 1;\n\t\t}\n\t\tlast_match_length = ctx->match_length;\n\t\tfor (i = 0; i < last_match_length && (c = getc(infile)) != EOF; i++) {\n\t\t\tDeleteNode(ctx, s);\n\t\t\tctx->text_buf[s] = c;\n\t\t\tif (s < F - 1)\n\t\t\t\tctx->text_buf[s + N] = c;\n\t\t\ts = (s + 1) & (N - 1);\n\t\t\tr = (r + 1) & (N - 1);\n\t\t\tInsertNode(ctx, r);\n\t\t}\n\t\tctx->textsize += i;\n\t\twhile (i++ < last_match_length) {\n\t\t\tDeleteNode(ctx, s);\n\t\t\ts = (s + 1) & (N - 1);\n\t\t\tr = (r + 1) & (N - 1);\n\t\t\tif (--len)\n\t\t\t\tInsertNode(ctx, r);\n\t\t}\n\t} while (len > 0);\n\tif (code_buf_ptr > 1) {\n\t\tfor (i = 0; i < code_buf_ptr; i++) {\n\t\t\tputc(code_buf[i], outfile);\n\t\t\tctx->codesize++;\n\t\t}\n\t}\n\tif(p_textsize)\n\t\t*p_textsize = ctx->textsize;\n\tif(p_codesize)\n\t\t*p_codesize = ctx->codesize;\n\tprintf(\"LZSS Out(%ld)/In(%ld): %.3f\\n\", ctx->codesize, ctx->textsize, (double)ctx->codesize / ctx->textsize);\n}\n\n/*\n * LZSS decodes the specified stream\n */\nvoid unlzss(struct lzhs_ctx *ctx, cursor_t *in, cursor_t *out) {\n\tint c, i, j, k, m, r = 0, flags = 0;\n\twhile (1) {\n\t\tif (((flags >>= 1) & 256) == 0) {\n\t\t\tif ((c = cgetc(in)) == EOF)\n\t\t\t\tbreak;\n\t\t\tflags = c | 0xff00;\n\t\t}\n\t\tif (flags & 1) {\n\t\t\tif((c = cgetc(in)) == EOF)\n\t\t\t\tbreak;\n\n\t\t\tif(cputc((ctx->text_buf[r++] = c), out) == EOF)\n\t\t\t\treturn;\n\t\t\tr &= (N - 1);\n\t\t} else {\n\t\t\tif((j = cgetc(in)) == EOF) // match length\n\t\t\t\tbreak;\n\t\t\tif((i = cgetc(in)) == EOF) // byte1 of match position\n\t\t\t\tbreak;\n\t\t\tif((m = cgetc(in)) == EOF) // byte0 of match position\n\t\t\t\tbreak;\n\n\t\t\ti = (i << 8) | m;\n\t\t\tfor (k = 0; k <= j + THRESHOLD; k++) {\n\t\t\t\tm = ctx->text_buf[(r - i) & (N - 1)];\n\t\t\t\tif(cputc((ctx->text_buf[r++] = m), out) == EOF)\n\t\t\t\t\treturn;\n\t\t\t\tr &= (N - 1);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/lzhs/lzhs_lib.c",
    "content": "/**\n * LZHS Encoder\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdbool.h>\n#include <string.h>\n#include <libgen.h>\n\n#include \"config.h\"\n#include \"mfile.h\"\n#include \"lzhs/lzhs.h\"\n#include \"mediatek.h\"\n#include \"util.h\"\n\n#define LZHS_SIZE_THRESHOLD (20 * 1024 * 1024) //20 MB (a random sane value)\n\nstatic bool lzhs_lookup_initialized = false;\n\nbool _is_lzhs_mem(struct lzhs_header *header){\n\tif (\n\t\t!memcmp(header->spare, \"\\0\\0\\0\\0\\0\\0\\0\", sizeof(header->spare)) &&\n\t\theader->compressedSize > 0 && header->compressedSize <= LZHS_SIZE_THRESHOLD &&\n\t\theader->uncompressedSize > 0 && header->uncompressedSize <= LZHS_SIZE_THRESHOLD\n\t){\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool is_lzhs_mem(MFILE *file, off_t offset){\n\tstruct lzhs_header *header = (struct lzhs_header *)(mdata(file, uint8_t) + offset);\n\tif(msize(file) < offset + sizeof(struct lzhs_header)){\n\t\treturn false;\n\t}\n\treturn _is_lzhs_mem(header);\n}\n\nMFILE *is_lzhs(const char *filename) {\n\tMFILE *file = mopen(filename, O_RDONLY);\n\tif (file == NULL) {\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\t}\n\tif(is_lzhs_mem(file, 0))\n\t\treturn file;\n\n\tmclose(file);\n\treturn NULL;\n}\n\nstatic void ARMThumb_Convert(unsigned char *data, uint32_t size, uint32_t nowPos, int encoding) {\n\tuint32_t i;\n\tfor (i = 0; i + 4 <= size; i += 2) {\n\t\tif ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) {\n\t\t\tuint32_t src = ((data[i + 1] & 0x7) << 19) | (data[i + 0] << 11) | ((data[i + 3] & 0x7) << 8) | (data[i + 2]);\n\t\t\tsrc <<= 1;\n\t\t\tuint32_t dest;\n\t\t\tif (encoding)\n\t\t\t\tdest = nowPos + i + 4 + src;\n\t\t\telse\n\t\t\t\tdest = src - (nowPos + i + 4);\n\t\t\tdest >>= 1;\n\t\t\tdata[i + 1] = 0xF0 | ((dest >> 19) & 0x7);\n\t\t\tdata[i + 0] = (dest >> 11);\n\t\t\tdata[i + 3] = 0xF8 | ((dest >> 8) & 0x7);\n\t\t\tdata[i + 2] = (dest);\n\t\t\ti += 2;\n\t\t}\n\t}\n}\n\nstatic int lzhs_pad_file(const char *filename, const char *outfilename) {\n\tint input_filesize;\n\tsize_t n;\n\tchar *ptr;\n\tFILE *infile, *outfile;\n\tinfile = fopen(filename, \"rb\");\n\tif (infile) {\n\t\toutfile = fopen(outfilename, \"wb\");\n\t\tif (outfile) {\n\t\t\tfseek(infile, 0, SEEK_END);\n\t\t\tsize_t filesize = ftell(infile);\n\t\t\trewind(infile);\n\t\t\tptr = malloc(sizeof(char) * filesize);\n\t\t\tint extrabytes = 0;\n\t\t\tfor (input_filesize = 0;; input_filesize += n) {\t//start a loop. add read elements every iteration\n\t\t\t\tn = fread(ptr, 1u, 0x200u, infile);\t//read 512 bytes from input into ptr\n\t\t\t\tif (n <= 0)\n\t\t\t\t\tbreak;\n\t\t\t\tif (n % 16 != 0) {\n\t\t\t\t\tunsigned int x = (n / 8) * 8;\t//it will be truncated, so we get next multiple\n\t\t\t\t\tif (x < n)\n\t\t\t\t\t\tx += 8;\n\t\t\t\t\tx = x - n;\t//how many bytes we need to add\n\t\t\t\t\textrabytes += x;\t//add the bytes to the counter\n\t\t\t\t}\n\t\t\t\tfwrite(ptr, 1u, n, outfile);\t//write read bytes to output\n\t\t\t}\n\t\t\tprintf(\"We need to fill extra %d bytes\\n\", extrabytes);\n\t\t\tint i;\n\t\t\tfor (i = 1; i <= extrabytes; i++)\n\t\t\t\tputc(0xff, outfile);\n\t\t\tfclose(infile);\n\t\t\tfclose(outfile);\n\t\t\treturn 0;\n\t\t} else {\n\t\t\tprintf(\"Open file %s failed.\\n\", outfilename);\n\t\t\treturn 1;\n\t\t}\n\t} else {\n\t\tprintf(\"open file %s fail \\n\", filename);\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nunsigned char lzhs_calc_checksum(unsigned char *buf, int fsize) {\n\tunsigned char checksum = 0;\n\tint i;\n\tfor (i = 0; i < fsize; ++i)\n\t\tchecksum += buf[i];\n\treturn checksum;\n}\n\nvoid lzhs_encode(const char *infile, const char *outfile) {\n\tstruct lzhs_header header;\n\tFILE *in, *out;\n\tunsigned char *buf;\n\tsize_t fsize;\n\n\tchar *outpath;\n\n\tunsigned long int textsize, codesize;\n\n\tstruct lzhs_ctx *ctx = lzhs_ctx_new();\n\n#if 1\n//// PADDING\n\tprintf(\"\\n[LZHS] Padding...\\n\");\n\tasprintf(&outpath, \"%s.tmp\", infile);\n\tlzhs_pad_file(infile, outpath);\n\tin = fopen(outpath, \"rb\");\n\tif (!in) {\n\t\terr_exit(\"Cannot open file %s\\n\", outpath);\n\t}\n\tfree(outpath);\n#else\n\tin = fopen(infile, \"rb\");\n#endif\n\n//// ARM 2 THUMB\n\tasprintf(&outpath, \"%s.conv\", infile);\n\tout = fopen(outpath, \"wb\");\n\tif (!out) {\n\t\terr_exit(\"Cannot open file conv\\n\");\n\t}\n\n\tfseek(in, 0, SEEK_END);\n\tfsize = ftell(in);\n\trewind(in);\n\n\tbuf = calloc(1, fsize);\n\tfread(buf, 1, fsize, in);\n\trewind(in);\n\n\tprintf(\"[LZHS] Calculating checksum...\\n\");\n\theader.checksum = lzhs_calc_checksum(buf, fsize);\n\tmemset(&header.spare, 0, sizeof(header.spare));\n\tprintf(\"Checksum = %x\\n\", header.checksum);\n\n\tprintf(\"[LZHS] Converting ARM => Thumb...\\n\");\n\tARMThumb_Convert(buf, fsize, 0, 1);\n\tfwrite(buf, 1, fsize, out);\n\n\tfree(buf);\n\n////LZSS\n\tfreopen(outpath, \"rb\", in);\n\tif (!in) {\n\t\terr_exit(\"Cannot open file conv\\n\");\n\t}\n\n\tfree(outpath);\n\tasprintf(&outpath, \"%s.lzs\", infile);\n\n\tfreopen(outpath, \"wb\", out);\n\n\tprintf(\"[LZHS] Encoding with LZSS...\\n\");\n\tlzss(ctx, in, out, &textsize, &codesize);\n\tif (!out) {\n\t\terr_exit(\"Cannot open tmp.lzs\\n\");\n\t}\n\n////HUFFMAN\n\tfreopen(outpath, \"rb\", in);\n\tif (!in) {\n\t\terr_exit(\"Cannot open file tmp.lzs\\n\");\n\t}\n\n\tfreopen(outfile, \"wb\", out);\n\tif (!out) {\n\t\terr_exit(\"Cannot open file %s\\n\", outfile);\n\t}\n\n\theader.uncompressedSize = fsize;\n\tfwrite(&header, 1, sizeof(header), out);\n\n\tprintf(\"[LZHS] Encoding with Huffman...\\n\");\n\n\thuff(ctx, in, out, &textsize, &codesize);\n\theader.compressedSize = codesize;\n\tprintf(\"[LZHS] Writing Header...\\n\");\n\trewind(out);\n\tfwrite(&header, 1, sizeof(header), out);\n\tprintf(\"[LZHS] Done!\\n\");\n\n\tfree(outpath);\n\n\tfclose(in);\n\tfclose(out);\n\n\tfree(ctx);\n}\n\ncursor_t *lzhs_decode(MFILE *in_file, off_t offset, const char *out_path, uint8_t *out_checksum){\n\tif(!lzhs_lookup_initialized){\n\t\tlzhs_init_lookup();\n\t\tlzhs_lookup_initialized = true;\n\t}\n\n\tstruct lzhs_header *header = (struct lzhs_header *)(mdata(in_file, uint8_t) + offset);\n\tprintf(\"\\n---LZHS details---\\n\");\n\tprintf(\"Compressed:\\t%u\\n\", header->compressedSize);\n\tprintf(\"Uncompressed:\\t%u\\n\", header->uncompressedSize);\n\tprintf(\"Checksum:\\t0x%x\\n\\n\", header->checksum);\n\n\n\t/*\n\t * There are a few cases where the huffman data can result in a bigger LZSS set than the final output size.\n\t * To work around this problem, we set temp memory to twice the uncompressedSize.\n\t */\n\tsize_t tempSize = header->uncompressedSize * 2;\n\n\tvoid *tmp = MFILE_ANON(tempSize);\n\tif(tmp == MAP_FAILED){\n\t\tperror(\"mmap tmp for lzhs\\n\");\n\t\treturn (cursor_t *)-1;\n\t}\n\tmemset(tmp, 0x00, tempSize);\n\n\tMFILE *out_file = NULL;\n\tuint8_t *out_bytes = NULL;\n\n\tif(out_path == NULL){\n\t\tout_bytes = MFILE_ANON(header->uncompressedSize);\n\t\tif(out_bytes == MAP_FAILED){\n\t\t\tperror(\"mmap out for lzhs\\n\");\n\t\t\treturn (cursor_t *)-1;\n\t\t}\n\t} else {\n\t\tout_file = mfopen(out_path, \"w+\");\n\t\tif(!out_file){\n\t\t\tfprintf(stderr, \"Cannot open output file %s\\n\", out_path);\n\t\t\treturn (cursor_t *)-1;\n\t\t}\n\t\tmfile_map(out_file, header->uncompressedSize);\n\t\tout_bytes = mdata(out_file, uint8_t);\n\t}\n\n\tuint8_t *in_bytes = mdata(in_file, uint8_t);\n\n\t/* Input file */\n\tcursor_t in_cur = {\n\t\t.ptr = in_bytes + offset + sizeof(*header),\n\t\t.size = header->compressedSize,\n\t\t.offset = 0\n\t};\n\n\t/* Temp memory */\n\tcursor_t out_cur = {\n\t\t.ptr = tmp,\n\t\t.size = tempSize,\n\t\t.offset = 0\n\t};\n\n\tstruct lzhs_ctx *ctx = lzhs_ctx_new();\n\n\tprintf(\"[LZHS] Decoding Huffman...\\n\");\n\t// Input file -> Temp memory\n\tunhuff(ctx, &in_cur, &out_cur);\n\n\tprintf(\"[LZHS] Decoding LZSS...\\n\");\n\n\t// Rewind the huffman cursor and change ends\n\tout_cur.offset = 0;\n\tmemcpy((void *)&in_cur, (void *)&out_cur, sizeof(cursor_t));\n\n\t// Setup output cursor for the final file\n\tout_cur.ptr = out_bytes;\n\tout_cur.size = header->uncompressedSize;\n\n\t// Temp memory -> Output file\n\tunlzss(ctx, &in_cur, &out_cur);\n\n\tfree(ctx);\n\n\t// We don't need the temp memory anymore\n\tmunmap(tmp, tempSize);\n\n\tprintf(\"[LZHS] Converting Thumb => ARM...\\n\");\n\tARMThumb_Convert(out_bytes, out_cur.size, 0, 0);\n\n\tprintf(\"[LZHS] Calculating checksum...\\n\");\n\tuint8_t checksum = lzhs_calc_checksum(out_bytes, out_cur.size);\n\tif(out_checksum != NULL){\n\t\t*out_checksum = checksum;\n\t}\n\tprintf(\"Calculated checksum = 0x%x\\n\", checksum);\n\tif (checksum != header->checksum)\n\t\tprintf(\"[LZHS] WARNING: Checksum mismatch (got 0x%x, expected 0x%x)!!\\n\", checksum, header->checksum);\n\tif (out_cur.size != header->uncompressedSize)\n\t\tprintf(\"[LZHS] WARNING: Size mismatch (got %zu, expected %u)!!\\n\", out_cur.size, header->uncompressedSize);\n\n\tif(out_file != NULL){\n\t\tmclose(out_file);\n\t\treturn NULL;\n\t} else {\n\t\tcursor_t *cpy = calloc(1, sizeof(out_cur));\n\t\tmemcpy(cpy, &out_cur, sizeof(out_cur));\n\t\treturn cpy;\n\t}\n}\n\nint process_lzhs_segment(MFILE *in_file, off_t offset, const char *name) {\n\tint r = 0;\n\tchar *file_dir = my_dirname(in_file->path);\n\n\tchar *out_path;\n\tasprintf(&out_path, \"%s/%s.lzhs\", file_dir, name);\n\tprintf(\"[MTK] Extracting %s to %s...\\n\", name, out_path);\n\n\tMFILE *out_file = mfopen(out_path, \"w+\");\n\tif (!out_file) {\n\t\tfprintf(stderr, \"Cannot open file %s for writing\\n\", out_path);\n\t\tr = -1;\n\t\tgoto exit;\n\t}\n\n\tuint8_t *bytes = &(mdata(in_file, uint8_t))[offset];\n\tstruct lzhs_header *lzhs_hdr = (struct lzhs_header *)bytes;\n\n\t/* Allocate file */\n\tmfile_map(out_file,\n\t\tsizeof(*lzhs_hdr) +\tlzhs_hdr->compressedSize\n\t);\n\n\t/* Copy compressed file */\n\tmemcpy(\n\t\t(void *)(mdata(out_file, uint8_t)),\n\t\t(void *)bytes,\n\t\tlzhs_hdr->compressedSize + sizeof(*lzhs_hdr)\n\t);\n\n\tprintf(\"[MTK] UnLZHS %s\\n\", out_path);\n\n\tasprintf(&out_path, \"%s/%s.unlzhs\", file_dir, name);\n\n\t// Decode the file we just wrote\n\tlzhs_decode(out_file, 0, out_path, NULL);\n\tmclose(out_file);\n\n\texit:\n\t\tfree(out_path);\n\t\tfree(file_dir);\n\t\treturn r;\n}\n\nint extract_lzhs(MFILE *in_file) {\n\tint r;\n\tif(is_lzhs_mem(in_file, MTK_LOADER_OFF) && (r=process_lzhs_segment(in_file, MTK_LOADER_OFF, \"mtkloader\")) < 0){\n\t\treturn r;\n\t} else if(is_lzhs_mem(in_file, MTK_LOADER_OFF1) && (r=process_lzhs_segment(in_file, MTK_LOADER_OFF1, \"mtkloader\")) < 0){\n\t\treturn r;\n\t}\n\n\tif(is_lzhs_mem(in_file, MTK_UBOOT_OFF) && (r=process_lzhs_segment(in_file, MTK_UBOOT_OFF, \"uboot\")) < 0)\n\t\treturn r;\n\tif(is_lzhs_mem(in_file, MTK_HISENSE_UBOOT_OFF) && (r=process_lzhs_segment(in_file, MTK_HISENSE_UBOOT_OFF, \"uboot\")) < 0)\n\t\treturn r;\n\n\n\tif(msize(in_file) < MTK_UBOOT_OFF){\n\t\treturn 0;\n\t}\n\tstruct lzhs_header *uboot_hdr = (struct lzhs_header *)(&(mdata(in_file, uint8_t))[MTK_UBOOT_OFF]);\n\n\tuint pad;\n\tpad = (pad = (uboot_hdr->compressedSize % 16)) == 0 ? 0 : (16 - pad);\n\n\toff_t mtk_tz = (\n\t\t//Offset of uboot\n\t\tMTK_UBOOT_OFF +\n\t\t//Size of its lzhs header\n\t\tsizeof(struct lzhs_header) +\n\t\t//uboot compressed size\n\t\tuboot_hdr->compressedSize +\n\t\t//Align to the next \"line\"\n\t\tpad +\n\t\t//TZ relative offset\n\t\tMTK_TZ_OFF\n\t);\n\n\t/* Do we have the TZ segment? (mtk5369 only) */\n\tif(mtk_tz < msize(in_file)){\n\t\tif(is_lzhs_mem(in_file, mtk_tz) && (r=process_lzhs_segment(in_file, mtk_tz, \"boot_tz\")) < 0)\n\t\t\treturn r;\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "src/lzma/CMakeLists.txt",
    "content": "add_library(lzma LzFind.c LzmaDec.c LzmaEnc.c)\ntarget_include_directories(lzma PUBLIC ${INC})"
  },
  {
    "path": "src/lzma/LzFind.c",
    "content": "/* LzFind.c -- Match finder for LZ algorithms\n2009-04-22 : Igor Pavlov : Public domain */\n\n#include <string.h>\n\n#include \"lzma/LzFind.h\"\n#include \"lzma/LzHash.h\"\n\n#define kEmptyHashValue 0\n#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)\n#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */\n#define kNormalizeMask (~(kNormalizeStepMin - 1))\n#define kMaxHistorySize ((UInt32)3 << 30)\n\n#define kStartMaxLen 3\n\nstatic void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)\n{\n  if (!p->directInput)\n  {\n    alloc->Free(alloc, p->bufferBase);\n    p->bufferBase = 0;\n  }\n}\n\n/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */\n\nstatic int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)\n{\n  UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;\n  if (p->directInput)\n  {\n    p->blockSize = blockSize;\n    return 1;\n  }\n  if (p->bufferBase == 0 || p->blockSize != blockSize)\n  {\n    LzInWindow_Free(p, alloc);\n    p->blockSize = blockSize;\n    p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);\n  }\n  return (p->bufferBase != 0);\n}\n\nByte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }\nByte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }\n\nUInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }\n\nvoid MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)\n{\n  p->posLimit -= subValue;\n  p->pos -= subValue;\n  p->streamPos -= subValue;\n}\n\nstatic void MatchFinder_ReadBlock(CMatchFinder *p)\n{\n  if (p->streamEndWasReached || p->result != SZ_OK)\n    return;\n  if (p->directInput)\n  {\n    UInt32 curSize = 0xFFFFFFFF - p->streamPos;\n    if (curSize > p->directInputRem)\n      curSize = (UInt32)p->directInputRem;\n    p->directInputRem -= curSize;\n    p->streamPos += curSize;\n    if (p->directInputRem == 0)\n      p->streamEndWasReached = 1;\n    return;\n  }\n  for (;;)\n  {\n    Byte *dest = p->buffer + (p->streamPos - p->pos);\n    size_t size = (p->bufferBase + p->blockSize - dest);\n    if (size == 0)\n      return;\n    p->result = p->stream->Read(p->stream, dest, &size);\n    if (p->result != SZ_OK)\n      return;\n    if (size == 0)\n    {\n      p->streamEndWasReached = 1;\n      return;\n    }\n    p->streamPos += (UInt32)size;\n    if (p->streamPos - p->pos > p->keepSizeAfter)\n      return;\n  }\n}\n\nvoid MatchFinder_MoveBlock(CMatchFinder *p)\n{\n  memmove(p->bufferBase,\n    p->buffer - p->keepSizeBefore,\n    (size_t)(p->streamPos - p->pos + p->keepSizeBefore));\n  p->buffer = p->bufferBase + p->keepSizeBefore;\n}\n\nint MatchFinder_NeedMove(CMatchFinder *p)\n{\n  if (p->directInput)\n    return 0;\n  /* if (p->streamEndWasReached) return 0; */\n  return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);\n}\n\nvoid MatchFinder_ReadIfRequired(CMatchFinder *p)\n{\n  if (p->streamEndWasReached)\n    return;\n  if (p->keepSizeAfter >= p->streamPos - p->pos)\n    MatchFinder_ReadBlock(p);\n}\n\nstatic void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)\n{\n  if (MatchFinder_NeedMove(p))\n    MatchFinder_MoveBlock(p);\n  MatchFinder_ReadBlock(p);\n}\n\nstatic void MatchFinder_SetDefaultSettings(CMatchFinder *p)\n{\n  p->cutValue = 32;\n  p->btMode = 1;\n  p->numHashBytes = 4;\n  p->bigHash = 0;\n}\n\n#define kCrcPoly 0xEDB88320\n\nvoid MatchFinder_Construct(CMatchFinder *p)\n{\n  UInt32 i;\n  p->bufferBase = 0;\n  p->directInput = 0;\n  p->hash = 0;\n  MatchFinder_SetDefaultSettings(p);\n\n  for (i = 0; i < 256; i++)\n  {\n    UInt32 r = i;\n    int j;\n    for (j = 0; j < 8; j++)\n      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));\n    p->crc[i] = r;\n  }\n}\n\nstatic void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)\n{\n  alloc->Free(alloc, p->hash);\n  p->hash = 0;\n}\n\nvoid MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)\n{\n  MatchFinder_FreeThisClassMemory(p, alloc);\n  LzInWindow_Free(p, alloc);\n}\n\nstatic CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)\n{\n  size_t sizeInBytes = (size_t)num * sizeof(CLzRef);\n  if (sizeInBytes / sizeof(CLzRef) != num)\n    return 0;\n  return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);\n}\n\nint MatchFinder_Create(CMatchFinder *p, UInt32 historySize,\n    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,\n    ISzAlloc *alloc)\n{\n  UInt32 sizeReserv;\n  if (historySize > kMaxHistorySize)\n  {\n    MatchFinder_Free(p, alloc);\n    return 0;\n  }\n  sizeReserv = historySize >> 1;\n  if (historySize > ((UInt32)2 << 30))\n    sizeReserv = historySize >> 2;\n  sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);\n\n  p->keepSizeBefore = historySize + keepAddBufferBefore + 1;\n  p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;\n  /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */\n  if (LzInWindow_Create(p, sizeReserv, alloc))\n  {\n    UInt32 newCyclicBufferSize = historySize + 1;\n    UInt32 hs;\n    p->matchMaxLen = matchMaxLen;\n    {\n      p->fixedHashSize = 0;\n      if (p->numHashBytes == 2)\n        hs = (1 << 16) - 1;\n      else\n      {\n        hs = historySize - 1;\n        hs |= (hs >> 1);\n        hs |= (hs >> 2);\n        hs |= (hs >> 4);\n        hs |= (hs >> 8);\n        hs >>= 1;\n        hs |= 0xFFFF; /* don't change it! It's required for Deflate */\n        if (hs > (1 << 24))\n        {\n          if (p->numHashBytes == 3)\n            hs = (1 << 24) - 1;\n          else\n            hs >>= 1;\n        }\n      }\n      p->hashMask = hs;\n      hs++;\n      if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;\n      if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;\n      if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;\n      hs += p->fixedHashSize;\n    }\n\n    {\n      UInt32 prevSize = p->hashSizeSum + p->numSons;\n      UInt32 newSize;\n      p->historySize = historySize;\n      p->hashSizeSum = hs;\n      p->cyclicBufferSize = newCyclicBufferSize;\n      p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);\n      newSize = p->hashSizeSum + p->numSons;\n      if (p->hash != 0 && prevSize == newSize)\n        return 1;\n      MatchFinder_FreeThisClassMemory(p, alloc);\n      p->hash = AllocRefs(newSize, alloc);\n      if (p->hash != 0)\n      {\n        p->son = p->hash + p->hashSizeSum;\n        return 1;\n      }\n    }\n  }\n  MatchFinder_Free(p, alloc);\n  return 0;\n}\n\nstatic void MatchFinder_SetLimits(CMatchFinder *p)\n{\n  UInt32 limit = kMaxValForNormalize - p->pos;\n  UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;\n  if (limit2 < limit)\n    limit = limit2;\n  limit2 = p->streamPos - p->pos;\n  if (limit2 <= p->keepSizeAfter)\n  {\n    if (limit2 > 0)\n      limit2 = 1;\n  }\n  else\n    limit2 -= p->keepSizeAfter;\n  if (limit2 < limit)\n    limit = limit2;\n  {\n    UInt32 lenLimit = p->streamPos - p->pos;\n    if (lenLimit > p->matchMaxLen)\n      lenLimit = p->matchMaxLen;\n    p->lenLimit = lenLimit;\n  }\n  p->posLimit = p->pos + limit;\n}\n\nvoid MatchFinder_Init(CMatchFinder *p)\n{\n  UInt32 i;\n  for (i = 0; i < p->hashSizeSum; i++)\n    p->hash[i] = kEmptyHashValue;\n  p->cyclicBufferPos = 0;\n  p->buffer = p->bufferBase;\n  p->pos = p->streamPos = p->cyclicBufferSize;\n  p->result = SZ_OK;\n  p->streamEndWasReached = 0;\n  MatchFinder_ReadBlock(p);\n  MatchFinder_SetLimits(p);\n}\n\nstatic UInt32 MatchFinder_GetSubValue(CMatchFinder *p)\n{\n  return (p->pos - p->historySize - 1) & kNormalizeMask;\n}\n\nvoid MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)\n{\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    UInt32 value = items[i];\n    if (value <= subValue)\n      value = kEmptyHashValue;\n    else\n      value -= subValue;\n    items[i] = value;\n  }\n}\n\nstatic void MatchFinder_Normalize(CMatchFinder *p)\n{\n  UInt32 subValue = MatchFinder_GetSubValue(p);\n  MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);\n  MatchFinder_ReduceOffsets(p, subValue);\n}\n\nstatic void MatchFinder_CheckLimits(CMatchFinder *p)\n{\n  if (p->pos == kMaxValForNormalize)\n    MatchFinder_Normalize(p);\n  if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)\n    MatchFinder_CheckAndMoveAndRead(p);\n  if (p->cyclicBufferPos == p->cyclicBufferSize)\n    p->cyclicBufferPos = 0;\n  MatchFinder_SetLimits(p);\n}\n\nstatic UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,\n    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,\n    UInt32 *distances, UInt32 maxLen)\n{\n  son[_cyclicBufferPos] = curMatch;\n  for (;;)\n  {\n    UInt32 delta = pos - curMatch;\n    if (cutValue-- == 0 || delta >= _cyclicBufferSize)\n      return distances;\n    {\n      const Byte *pb = cur - delta;\n      curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];\n      if (pb[maxLen] == cur[maxLen] && *pb == *cur)\n      {\n        UInt32 len = 0;\n        while (++len != lenLimit)\n          if (pb[len] != cur[len])\n            break;\n        if (maxLen < len)\n        {\n          *distances++ = maxLen = len;\n          *distances++ = delta - 1;\n          if (len == lenLimit)\n            return distances;\n        }\n      }\n    }\n  }\n}\n\nUInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,\n    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,\n    UInt32 *distances, UInt32 maxLen)\n{\n  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;\n  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);\n  UInt32 len0 = 0, len1 = 0;\n  for (;;)\n  {\n    UInt32 delta = pos - curMatch;\n    if (cutValue-- == 0 || delta >= _cyclicBufferSize)\n    {\n      *ptr0 = *ptr1 = kEmptyHashValue;\n      return distances;\n    }\n    {\n      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);\n      const Byte *pb = cur - delta;\n      UInt32 len = (len0 < len1 ? len0 : len1);\n      if (pb[len] == cur[len])\n      {\n        if (++len != lenLimit && pb[len] == cur[len])\n          while (++len != lenLimit)\n            if (pb[len] != cur[len])\n              break;\n        if (maxLen < len)\n        {\n          *distances++ = maxLen = len;\n          *distances++ = delta - 1;\n          if (len == lenLimit)\n          {\n            *ptr1 = pair[0];\n            *ptr0 = pair[1];\n            return distances;\n          }\n        }\n      }\n      if (pb[len] < cur[len])\n      {\n        *ptr1 = curMatch;\n        ptr1 = pair + 1;\n        curMatch = *ptr1;\n        len1 = len;\n      }\n      else\n      {\n        *ptr0 = curMatch;\n        ptr0 = pair;\n        curMatch = *ptr0;\n        len0 = len;\n      }\n    }\n  }\n}\n\nstatic void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,\n    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)\n{\n  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;\n  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);\n  UInt32 len0 = 0, len1 = 0;\n  for (;;)\n  {\n    UInt32 delta = pos - curMatch;\n    if (cutValue-- == 0 || delta >= _cyclicBufferSize)\n    {\n      *ptr0 = *ptr1 = kEmptyHashValue;\n      return;\n    }\n    {\n      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);\n      const Byte *pb = cur - delta;\n      UInt32 len = (len0 < len1 ? len0 : len1);\n      if (pb[len] == cur[len])\n      {\n        while (++len != lenLimit)\n          if (pb[len] != cur[len])\n            break;\n        {\n          if (len == lenLimit)\n          {\n            *ptr1 = pair[0];\n            *ptr0 = pair[1];\n            return;\n          }\n        }\n      }\n      if (pb[len] < cur[len])\n      {\n        *ptr1 = curMatch;\n        ptr1 = pair + 1;\n        curMatch = *ptr1;\n        len1 = len;\n      }\n      else\n      {\n        *ptr0 = curMatch;\n        ptr0 = pair;\n        curMatch = *ptr0;\n        len0 = len;\n      }\n    }\n  }\n}\n\n#define MOVE_POS \\\n  ++p->cyclicBufferPos; \\\n  p->buffer++; \\\n  if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);\n\n#define MOVE_POS_RET MOVE_POS return offset;\n\nstatic void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }\n\n#define GET_MATCHES_HEADER2(minLen, ret_op) \\\n  UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \\\n  lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \\\n  cur = p->buffer;\n\n#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)\n#define SKIP_HEADER(minLen)        GET_MATCHES_HEADER2(minLen, continue)\n\n#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue\n\n#define GET_MATCHES_FOOTER(offset, maxLen) \\\n  offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \\\n  distances + offset, maxLen) - distances); MOVE_POS_RET;\n\n#define SKIP_FOOTER \\\n  SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;\n\nstatic UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\n{\n  UInt32 offset;\n  GET_MATCHES_HEADER(2)\n  HASH2_CALC;\n  curMatch = p->hash[hashValue];\n  p->hash[hashValue] = p->pos;\n  offset = 0;\n  GET_MATCHES_FOOTER(offset, 1)\n}\n\nUInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\n{\n  UInt32 offset;\n  GET_MATCHES_HEADER(3)\n  HASH_ZIP_CALC;\n  curMatch = p->hash[hashValue];\n  p->hash[hashValue] = p->pos;\n  offset = 0;\n  GET_MATCHES_FOOTER(offset, 2)\n}\n\nstatic UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\n{\n  UInt32 hash2Value, delta2, maxLen, offset;\n  GET_MATCHES_HEADER(3)\n\n  HASH3_CALC;\n\n  delta2 = p->pos - p->hash[hash2Value];\n  curMatch = p->hash[kFix3HashSize + hashValue];\n\n  p->hash[hash2Value] =\n  p->hash[kFix3HashSize + hashValue] = p->pos;\n\n\n  maxLen = 2;\n  offset = 0;\n  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)\n  {\n    for (; maxLen != lenLimit; maxLen++)\n      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])\n        break;\n    distances[0] = maxLen;\n    distances[1] = delta2 - 1;\n    offset = 2;\n    if (maxLen == lenLimit)\n    {\n      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));\n      MOVE_POS_RET;\n    }\n  }\n  GET_MATCHES_FOOTER(offset, maxLen)\n}\n\nstatic UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\n{\n  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;\n  GET_MATCHES_HEADER(4)\n\n  HASH4_CALC;\n\n  delta2 = p->pos - p->hash[                hash2Value];\n  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];\n  curMatch = p->hash[kFix4HashSize + hashValue];\n\n  p->hash[                hash2Value] =\n  p->hash[kFix3HashSize + hash3Value] =\n  p->hash[kFix4HashSize + hashValue] = p->pos;\n\n  maxLen = 1;\n  offset = 0;\n  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)\n  {\n    distances[0] = maxLen = 2;\n    distances[1] = delta2 - 1;\n    offset = 2;\n  }\n  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)\n  {\n    maxLen = 3;\n    distances[offset + 1] = delta3 - 1;\n    offset += 2;\n    delta2 = delta3;\n  }\n  if (offset != 0)\n  {\n    for (; maxLen != lenLimit; maxLen++)\n      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])\n        break;\n    distances[offset - 2] = maxLen;\n    if (maxLen == lenLimit)\n    {\n      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));\n      MOVE_POS_RET;\n    }\n  }\n  if (maxLen < 3)\n    maxLen = 3;\n  GET_MATCHES_FOOTER(offset, maxLen)\n}\n\nstatic UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\n{\n  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;\n  GET_MATCHES_HEADER(4)\n\n  HASH4_CALC;\n\n  delta2 = p->pos - p->hash[                hash2Value];\n  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];\n  curMatch = p->hash[kFix4HashSize + hashValue];\n\n  p->hash[                hash2Value] =\n  p->hash[kFix3HashSize + hash3Value] =\n  p->hash[kFix4HashSize + hashValue] = p->pos;\n\n  maxLen = 1;\n  offset = 0;\n  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)\n  {\n    distances[0] = maxLen = 2;\n    distances[1] = delta2 - 1;\n    offset = 2;\n  }\n  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)\n  {\n    maxLen = 3;\n    distances[offset + 1] = delta3 - 1;\n    offset += 2;\n    delta2 = delta3;\n  }\n  if (offset != 0)\n  {\n    for (; maxLen != lenLimit; maxLen++)\n      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])\n        break;\n    distances[offset - 2] = maxLen;\n    if (maxLen == lenLimit)\n    {\n      p->son[p->cyclicBufferPos] = curMatch;\n      MOVE_POS_RET;\n    }\n  }\n  if (maxLen < 3)\n    maxLen = 3;\n  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),\n    distances + offset, maxLen) - (distances));\n  MOVE_POS_RET\n}\n\nUInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\n{\n  UInt32 offset;\n  GET_MATCHES_HEADER(3)\n  HASH_ZIP_CALC;\n  curMatch = p->hash[hashValue];\n  p->hash[hashValue] = p->pos;\n  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),\n    distances, 2) - (distances));\n  MOVE_POS_RET\n}\n\nstatic void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\n{\n  do\n  {\n    SKIP_HEADER(2)\n    HASH2_CALC;\n    curMatch = p->hash[hashValue];\n    p->hash[hashValue] = p->pos;\n    SKIP_FOOTER\n  }\n  while (--num != 0);\n}\n\nvoid Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\n{\n  do\n  {\n    SKIP_HEADER(3)\n    HASH_ZIP_CALC;\n    curMatch = p->hash[hashValue];\n    p->hash[hashValue] = p->pos;\n    SKIP_FOOTER\n  }\n  while (--num != 0);\n}\n\nstatic void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\n{\n  do\n  {\n    UInt32 hash2Value;\n    SKIP_HEADER(3)\n    HASH3_CALC;\n    curMatch = p->hash[kFix3HashSize + hashValue];\n    p->hash[hash2Value] =\n    p->hash[kFix3HashSize + hashValue] = p->pos;\n    SKIP_FOOTER\n  }\n  while (--num != 0);\n}\n\nstatic void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\n{\n  do\n  {\n    UInt32 hash2Value, hash3Value;\n    SKIP_HEADER(4)\n    HASH4_CALC;\n    curMatch = p->hash[kFix4HashSize + hashValue];\n    p->hash[                hash2Value] =\n    p->hash[kFix3HashSize + hash3Value] = p->pos;\n    p->hash[kFix4HashSize + hashValue] = p->pos;\n    SKIP_FOOTER\n  }\n  while (--num != 0);\n}\n\nstatic void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\n{\n  do\n  {\n    UInt32 hash2Value, hash3Value;\n    SKIP_HEADER(4)\n    HASH4_CALC;\n    curMatch = p->hash[kFix4HashSize + hashValue];\n    p->hash[                hash2Value] =\n    p->hash[kFix3HashSize + hash3Value] =\n    p->hash[kFix4HashSize + hashValue] = p->pos;\n    p->son[p->cyclicBufferPos] = curMatch;\n    MOVE_POS\n  }\n  while (--num != 0);\n}\n\nvoid Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\n{\n  do\n  {\n    SKIP_HEADER(3)\n    HASH_ZIP_CALC;\n    curMatch = p->hash[hashValue];\n    p->hash[hashValue] = p->pos;\n    p->son[p->cyclicBufferPos] = curMatch;\n    MOVE_POS\n  }\n  while (--num != 0);\n}\n\nvoid MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)\n{\n  vTable->Init = (Mf_Init_Func)MatchFinder_Init;\n  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;\n  vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;\n  vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;\n  if (!p->btMode)\n  {\n    vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;\n    vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;\n  }\n  else if (p->numHashBytes == 2)\n  {\n    vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;\n    vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;\n  }\n  else if (p->numHashBytes == 3)\n  {\n    vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;\n    vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;\n  }\n  else\n  {\n    vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;\n    vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;\n  }\n}\n"
  },
  {
    "path": "src/lzma/LzmaDec.c",
    "content": "/* LzmaDec.c -- LZMA Decoder\n2009-09-20 : Igor Pavlov : Public domain */\n\n#include \"lzma/LzmaDec.h\"\n\n#include <string.h>\n\n#define kNumTopBits 24\n#define kTopValue ((UInt32)1 << kNumTopBits)\n\n#define kNumBitModelTotalBits 11\n#define kBitModelTotal (1 << kNumBitModelTotalBits)\n#define kNumMoveBits 5\n\n#define RC_INIT_SIZE 5\n\n#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }\n\n#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)\n#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\n#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));\n#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \\\n  { UPDATE_0(p); i = (i + i); A0; } else \\\n  { UPDATE_1(p); i = (i + i) + 1; A1; }\n#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)\n\n#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }\n#define TREE_DECODE(probs, limit, i) \\\n  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }\n\n/* #define _LZMA_SIZE_OPT */\n\n#ifdef _LZMA_SIZE_OPT\n#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)\n#else\n#define TREE_6_DECODE(probs, i) \\\n  { i = 1; \\\n  TREE_GET_BIT(probs, i); \\\n  TREE_GET_BIT(probs, i); \\\n  TREE_GET_BIT(probs, i); \\\n  TREE_GET_BIT(probs, i); \\\n  TREE_GET_BIT(probs, i); \\\n  TREE_GET_BIT(probs, i); \\\n  i -= 0x40; }\n#endif\n\n#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }\n\n#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)\n#define UPDATE_0_CHECK range = bound;\n#define UPDATE_1_CHECK range -= bound; code -= bound;\n#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \\\n  { UPDATE_0_CHECK; i = (i + i); A0; } else \\\n  { UPDATE_1_CHECK; i = (i + i) + 1; A1; }\n#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)\n#define TREE_DECODE_CHECK(probs, limit, i) \\\n  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }\n\n\n#define kNumPosBitsMax 4\n#define kNumPosStatesMax (1 << kNumPosBitsMax)\n\n#define kLenNumLowBits 3\n#define kLenNumLowSymbols (1 << kLenNumLowBits)\n#define kLenNumMidBits 3\n#define kLenNumMidSymbols (1 << kLenNumMidBits)\n#define kLenNumHighBits 8\n#define kLenNumHighSymbols (1 << kLenNumHighBits)\n\n#define LenChoice 0\n#define LenChoice2 (LenChoice + 1)\n#define LenLow (LenChoice2 + 1)\n#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))\n#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))\n#define kNumLenProbs (LenHigh + kLenNumHighSymbols)\n\n\n#define kNumStates 12\n#define kNumLitStates 7\n\n#define kStartPosModelIndex 4\n#define kEndPosModelIndex 14\n#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\n\n#define kNumPosSlotBits 6\n#define kNumLenToPosStates 4\n\n#define kNumAlignBits 4\n#define kAlignTableSize (1 << kNumAlignBits)\n\n#define kMatchMinLen 2\n#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)\n\n#define IsMatch 0\n#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))\n#define IsRepG0 (IsRep + kNumStates)\n#define IsRepG1 (IsRepG0 + kNumStates)\n#define IsRepG2 (IsRepG1 + kNumStates)\n#define IsRep0Long (IsRepG2 + kNumStates)\n#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))\n#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))\n#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)\n#define LenCoder (Align + kAlignTableSize)\n#define RepLenCoder (LenCoder + kNumLenProbs)\n#define Literal (RepLenCoder + kNumLenProbs)\n\n#define LZMA_BASE_SIZE 1846\n#define LZMA_LIT_SIZE 768\n\n#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))\n\n#if Literal != LZMA_BASE_SIZE\nStopCompilingDueBUG\n#endif\n\n#define LZMA_DIC_MIN (1 << 12)\n\n/* First LZMA-symbol is always decoded.\nAnd it decodes new LZMA-symbols while (buf < bufLimit), but \"buf\" is without last normalization\nOut:\n  Result:\n    SZ_OK - OK\n    SZ_ERROR_DATA - Error\n  p->remainLen:\n    < kMatchSpecLenStart : normal remain\n    = kMatchSpecLenStart : finished\n    = kMatchSpecLenStart + 1 : Flush marker\n    = kMatchSpecLenStart + 2 : State Init Marker\n*/\n\nstatic int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\n{\n  CLzmaProb *probs = p->probs;\n\n  unsigned state = p->state;\n  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];\n  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;\n  unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;\n  unsigned lc = p->prop.lc;\n\n  Byte *dic = p->dic;\n  SizeT dicBufSize = p->dicBufSize;\n  SizeT dicPos = p->dicPos;\n\n  UInt32 processedPos = p->processedPos;\n  UInt32 checkDicSize = p->checkDicSize;\n  unsigned len = 0;\n\n  const Byte *buf = p->buf;\n  UInt32 range = p->range;\n  UInt32 code = p->code;\n\n  do\n  {\n    CLzmaProb *prob;\n    UInt32 bound;\n    unsigned ttt;\n    unsigned posState = processedPos & pbMask;\n\n    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;\n    IF_BIT_0(prob)\n    {\n      unsigned symbol;\n      UPDATE_0(prob);\n      prob = probs + Literal;\n      if (checkDicSize != 0 || processedPos != 0)\n        prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +\n        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));\n\n      if (state < kNumLitStates)\n      {\n        state -= (state < 4) ? state : 3;\n        symbol = 1;\n        do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);\n      }\n      else\n      {\n        unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];\n        unsigned offs = 0x100;\n        state -= (state < 10) ? 3 : 6;\n        symbol = 1;\n        do\n        {\n          unsigned bit;\n          CLzmaProb *probLit;\n          matchByte <<= 1;\n          bit = (matchByte & offs);\n          probLit = prob + offs + bit + symbol;\n          GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)\n        }\n        while (symbol < 0x100);\n      }\n      dic[dicPos++] = (Byte)symbol;\n      processedPos++;\n      continue;\n    }\n    else\n    {\n      UPDATE_1(prob);\n      prob = probs + IsRep + state;\n      IF_BIT_0(prob)\n      {\n        UPDATE_0(prob);\n        state += kNumStates;\n        prob = probs + LenCoder;\n      }\n      else\n      {\n        UPDATE_1(prob);\n        if (checkDicSize == 0 && processedPos == 0)\n          return SZ_ERROR_DATA;\n        prob = probs + IsRepG0 + state;\n        IF_BIT_0(prob)\n        {\n          UPDATE_0(prob);\n          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;\n          IF_BIT_0(prob)\n          {\n            UPDATE_0(prob);\n            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];\n            dicPos++;\n            processedPos++;\n            state = state < kNumLitStates ? 9 : 11;\n            continue;\n          }\n          UPDATE_1(prob);\n        }\n        else\n        {\n          UInt32 distance;\n          UPDATE_1(prob);\n          prob = probs + IsRepG1 + state;\n          IF_BIT_0(prob)\n          {\n            UPDATE_0(prob);\n            distance = rep1;\n          }\n          else\n          {\n            UPDATE_1(prob);\n            prob = probs + IsRepG2 + state;\n            IF_BIT_0(prob)\n            {\n              UPDATE_0(prob);\n              distance = rep2;\n            }\n            else\n            {\n              UPDATE_1(prob);\n              distance = rep3;\n              rep3 = rep2;\n            }\n            rep2 = rep1;\n          }\n          rep1 = rep0;\n          rep0 = distance;\n        }\n        state = state < kNumLitStates ? 8 : 11;\n        prob = probs + RepLenCoder;\n      }\n      {\n        unsigned limit, offset;\n        CLzmaProb *probLen = prob + LenChoice;\n        IF_BIT_0(probLen)\n        {\n          UPDATE_0(probLen);\n          probLen = prob + LenLow + (posState << kLenNumLowBits);\n          offset = 0;\n          limit = (1 << kLenNumLowBits);\n        }\n        else\n        {\n          UPDATE_1(probLen);\n          probLen = prob + LenChoice2;\n          IF_BIT_0(probLen)\n          {\n            UPDATE_0(probLen);\n            probLen = prob + LenMid + (posState << kLenNumMidBits);\n            offset = kLenNumLowSymbols;\n            limit = (1 << kLenNumMidBits);\n          }\n          else\n          {\n            UPDATE_1(probLen);\n            probLen = prob + LenHigh;\n            offset = kLenNumLowSymbols + kLenNumMidSymbols;\n            limit = (1 << kLenNumHighBits);\n          }\n        }\n        TREE_DECODE(probLen, limit, len);\n        len += offset;\n      }\n\n      if (state >= kNumStates)\n      {\n        UInt32 distance;\n        prob = probs + PosSlot +\n            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);\n        TREE_6_DECODE(prob, distance);\n        if (distance >= kStartPosModelIndex)\n        {\n          unsigned posSlot = (unsigned)distance;\n          int numDirectBits = (int)(((distance >> 1) - 1));\n          distance = (2 | (distance & 1));\n          if (posSlot < kEndPosModelIndex)\n          {\n            distance <<= numDirectBits;\n            prob = probs + SpecPos + distance - posSlot - 1;\n            {\n              UInt32 mask = 1;\n              unsigned i = 1;\n              do\n              {\n                GET_BIT2(prob + i, i, ; , distance |= mask);\n                mask <<= 1;\n              }\n              while (--numDirectBits != 0);\n            }\n          }\n          else\n          {\n            numDirectBits -= kNumAlignBits;\n            do\n            {\n              NORMALIZE\n              range >>= 1;\n\n              {\n                UInt32 t;\n                code -= range;\n                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */\n                distance = (distance << 1) + (t + 1);\n                code += range & t;\n              }\n              /*\n              distance <<= 1;\n              if (code >= range)\n              {\n                code -= range;\n                distance |= 1;\n              }\n              */\n            }\n            while (--numDirectBits != 0);\n            prob = probs + Align;\n            distance <<= kNumAlignBits;\n            {\n              unsigned i = 1;\n              GET_BIT2(prob + i, i, ; , distance |= 1);\n              GET_BIT2(prob + i, i, ; , distance |= 2);\n              GET_BIT2(prob + i, i, ; , distance |= 4);\n              GET_BIT2(prob + i, i, ; , distance |= 8);\n            }\n            if (distance == (UInt32)0xFFFFFFFF)\n            {\n              len += kMatchSpecLenStart;\n              state -= kNumStates;\n              break;\n            }\n          }\n        }\n        rep3 = rep2;\n        rep2 = rep1;\n        rep1 = rep0;\n        rep0 = distance + 1;\n        if (checkDicSize == 0)\n        {\n          if (distance >= processedPos)\n            return SZ_ERROR_DATA;\n        }\n        else if (distance >= checkDicSize)\n          return SZ_ERROR_DATA;\n        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;\n      }\n\n      len += kMatchMinLen;\n\n      if (limit == dicPos)\n        return SZ_ERROR_DATA;\n      {\n        SizeT rem = limit - dicPos;\n        unsigned curLen = ((rem < len) ? (unsigned)rem : len);\n        SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);\n\n        processedPos += curLen;\n\n        len -= curLen;\n        if (pos + curLen <= dicBufSize)\n        {\n          Byte *dest = dic + dicPos;\n          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;\n          const Byte *lim = dest + curLen;\n          dicPos += curLen;\n          do\n            *(dest) = (Byte)*(dest + src);\n          while (++dest != lim);\n        }\n        else\n        {\n          do\n          {\n            dic[dicPos++] = dic[pos];\n            if (++pos == dicBufSize)\n              pos = 0;\n          }\n          while (--curLen != 0);\n        }\n      }\n    }\n  }\n  while (dicPos < limit && buf < bufLimit);\n  NORMALIZE;\n  p->buf = buf;\n  p->range = range;\n  p->code = code;\n  p->remainLen = len;\n  p->dicPos = dicPos;\n  p->processedPos = processedPos;\n  p->reps[0] = rep0;\n  p->reps[1] = rep1;\n  p->reps[2] = rep2;\n  p->reps[3] = rep3;\n  p->state = state;\n\n  return SZ_OK;\n}\n\nstatic void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)\n{\n  if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)\n  {\n    Byte *dic = p->dic;\n    SizeT dicPos = p->dicPos;\n    SizeT dicBufSize = p->dicBufSize;\n    unsigned len = p->remainLen;\n    UInt32 rep0 = p->reps[0];\n    if (limit - dicPos < len)\n      len = (unsigned)(limit - dicPos);\n\n    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)\n      p->checkDicSize = p->prop.dicSize;\n\n    p->processedPos += len;\n    p->remainLen -= len;\n    while (len-- != 0)\n    {\n      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];\n      dicPos++;\n    }\n    p->dicPos = dicPos;\n  }\n}\n\nstatic int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\n{\n  do\n  {\n    SizeT limit2 = limit;\n    if (p->checkDicSize == 0)\n    {\n      UInt32 rem = p->prop.dicSize - p->processedPos;\n      if (limit - p->dicPos > rem)\n        limit2 = p->dicPos + rem;\n    }\n    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));\n    if (p->processedPos >= p->prop.dicSize)\n      p->checkDicSize = p->prop.dicSize;\n    LzmaDec_WriteRem(p, limit);\n  }\n  while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);\n\n  if (p->remainLen > kMatchSpecLenStart)\n  {\n    p->remainLen = kMatchSpecLenStart;\n  }\n  return 0;\n}\n\ntypedef enum\n{\n  DUMMY_ERROR, /* unexpected end of input stream */\n  DUMMY_LIT,\n  DUMMY_MATCH,\n  DUMMY_REP\n} ELzmaDummy;\n\nstatic ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)\n{\n  UInt32 range = p->range;\n  UInt32 code = p->code;\n  const Byte *bufLimit = buf + inSize;\n  CLzmaProb *probs = p->probs;\n  unsigned state = p->state;\n  ELzmaDummy res;\n\n  {\n    CLzmaProb *prob;\n    UInt32 bound;\n    unsigned ttt;\n    unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);\n\n    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;\n    IF_BIT_0_CHECK(prob)\n    {\n      UPDATE_0_CHECK\n\n      /* if (bufLimit - buf >= 7) return DUMMY_LIT; */\n\n      prob = probs + Literal;\n      if (p->checkDicSize != 0 || p->processedPos != 0)\n        prob += (LZMA_LIT_SIZE *\n          ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +\n          (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));\n\n      if (state < kNumLitStates)\n      {\n        unsigned symbol = 1;\n        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);\n      }\n      else\n      {\n        unsigned matchByte = p->dic[p->dicPos - p->reps[0] +\n            ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];\n        unsigned offs = 0x100;\n        unsigned symbol = 1;\n        do\n        {\n          unsigned bit;\n          CLzmaProb *probLit;\n          matchByte <<= 1;\n          bit = (matchByte & offs);\n          probLit = prob + offs + bit + symbol;\n          GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)\n        }\n        while (symbol < 0x100);\n      }\n      res = DUMMY_LIT;\n    }\n    else\n    {\n      unsigned len;\n      UPDATE_1_CHECK;\n\n      prob = probs + IsRep + state;\n      IF_BIT_0_CHECK(prob)\n      {\n        UPDATE_0_CHECK;\n        state = 0;\n        prob = probs + LenCoder;\n        res = DUMMY_MATCH;\n      }\n      else\n      {\n        UPDATE_1_CHECK;\n        res = DUMMY_REP;\n        prob = probs + IsRepG0 + state;\n        IF_BIT_0_CHECK(prob)\n        {\n          UPDATE_0_CHECK;\n          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;\n          IF_BIT_0_CHECK(prob)\n          {\n            UPDATE_0_CHECK;\n            NORMALIZE_CHECK;\n            return DUMMY_REP;\n          }\n          else\n          {\n            UPDATE_1_CHECK;\n          }\n        }\n        else\n        {\n          UPDATE_1_CHECK;\n          prob = probs + IsRepG1 + state;\n          IF_BIT_0_CHECK(prob)\n          {\n            UPDATE_0_CHECK;\n          }\n          else\n          {\n            UPDATE_1_CHECK;\n            prob = probs + IsRepG2 + state;\n            IF_BIT_0_CHECK(prob)\n            {\n              UPDATE_0_CHECK;\n            }\n            else\n            {\n              UPDATE_1_CHECK;\n            }\n          }\n        }\n        state = kNumStates;\n        prob = probs + RepLenCoder;\n      }\n      {\n        unsigned limit, offset;\n        CLzmaProb *probLen = prob + LenChoice;\n        IF_BIT_0_CHECK(probLen)\n        {\n          UPDATE_0_CHECK;\n          probLen = prob + LenLow + (posState << kLenNumLowBits);\n          offset = 0;\n          limit = 1 << kLenNumLowBits;\n        }\n        else\n        {\n          UPDATE_1_CHECK;\n          probLen = prob + LenChoice2;\n          IF_BIT_0_CHECK(probLen)\n          {\n            UPDATE_0_CHECK;\n            probLen = prob + LenMid + (posState << kLenNumMidBits);\n            offset = kLenNumLowSymbols;\n            limit = 1 << kLenNumMidBits;\n          }\n          else\n          {\n            UPDATE_1_CHECK;\n            probLen = prob + LenHigh;\n            offset = kLenNumLowSymbols + kLenNumMidSymbols;\n            limit = 1 << kLenNumHighBits;\n          }\n        }\n        TREE_DECODE_CHECK(probLen, limit, len);\n        len += offset;\n      }\n\n      if (state < 4)\n      {\n        unsigned posSlot;\n        prob = probs + PosSlot +\n            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<\n            kNumPosSlotBits);\n        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);\n        if (posSlot >= kStartPosModelIndex)\n        {\n          int numDirectBits = ((posSlot >> 1) - 1);\n\n          /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */\n\n          if (posSlot < kEndPosModelIndex)\n          {\n            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;\n          }\n          else\n          {\n            numDirectBits -= kNumAlignBits;\n            do\n            {\n              NORMALIZE_CHECK\n              range >>= 1;\n              code -= range & (((code - range) >> 31) - 1);\n              /* if (code >= range) code -= range; */\n            }\n            while (--numDirectBits != 0);\n            prob = probs + Align;\n            numDirectBits = kNumAlignBits;\n          }\n          {\n            unsigned i = 1;\n            do\n            {\n              GET_BIT_CHECK(prob + i, i);\n            }\n            while (--numDirectBits != 0);\n          }\n        }\n      }\n    }\n  }\n  NORMALIZE_CHECK;\n  return res;\n}\n\n\nstatic void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)\n{\n  p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);\n  p->range = 0xFFFFFFFF;\n  p->needFlush = 0;\n}\n\nvoid LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)\n{\n  p->needFlush = 1;\n  p->remainLen = 0;\n  p->tempBufSize = 0;\n\n  if (initDic)\n  {\n    p->processedPos = 0;\n    p->checkDicSize = 0;\n    p->needInitState = 1;\n  }\n  if (initState)\n    p->needInitState = 1;\n}\n\nvoid LzmaDec_Init(CLzmaDec *p)\n{\n  p->dicPos = 0;\n  LzmaDec_InitDicAndState(p, True, True);\n}\n\nstatic void LzmaDec_InitStateReal(CLzmaDec *p)\n{\n  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));\n  UInt32 i;\n  CLzmaProb *probs = p->probs;\n  for (i = 0; i < numProbs; i++)\n    probs[i] = kBitModelTotal >> 1;\n  p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;\n  p->state = 0;\n  p->needInitState = 0;\n}\n\nSRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,\n    ELzmaFinishMode finishMode, ELzmaStatus *status)\n{\n  SizeT inSize = *srcLen;\n  (*srcLen) = 0;\n  LzmaDec_WriteRem(p, dicLimit);\n\n  *status = LZMA_STATUS_NOT_SPECIFIED;\n\n  while (p->remainLen != kMatchSpecLenStart)\n  {\n      int checkEndMarkNow;\n\n      if (p->needFlush != 0)\n      {\n        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)\n          p->tempBuf[p->tempBufSize++] = *src++;\n        if (p->tempBufSize < RC_INIT_SIZE)\n        {\n          *status = LZMA_STATUS_NEEDS_MORE_INPUT;\n          return SZ_OK;\n        }\n        if (p->tempBuf[0] != 0)\n          return SZ_ERROR_DATA;\n\n        LzmaDec_InitRc(p, p->tempBuf);\n        p->tempBufSize = 0;\n      }\n\n      checkEndMarkNow = 0;\n      if (p->dicPos >= dicLimit)\n      {\n        if (p->remainLen == 0 && p->code == 0)\n        {\n          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;\n          return SZ_OK;\n        }\n        if (finishMode == LZMA_FINISH_ANY)\n        {\n          *status = LZMA_STATUS_NOT_FINISHED;\n          return SZ_OK;\n        }\n        if (p->remainLen != 0)\n        {\n          *status = LZMA_STATUS_NOT_FINISHED;\n          return SZ_ERROR_DATA;\n        }\n        checkEndMarkNow = 1;\n      }\n\n      if (p->needInitState)\n        LzmaDec_InitStateReal(p);\n\n      if (p->tempBufSize == 0)\n      {\n        SizeT processed;\n        const Byte *bufLimit;\n        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\n        {\n          int dummyRes = LzmaDec_TryDummy(p, src, inSize);\n          if (dummyRes == DUMMY_ERROR)\n          {\n            memcpy(p->tempBuf, src, inSize);\n            p->tempBufSize = (unsigned)inSize;\n            (*srcLen) += inSize;\n            *status = LZMA_STATUS_NEEDS_MORE_INPUT;\n            return SZ_OK;\n          }\n          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)\n          {\n            *status = LZMA_STATUS_NOT_FINISHED;\n            return SZ_ERROR_DATA;\n          }\n          bufLimit = src;\n        }\n        else\n          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;\n        p->buf = src;\n        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)\n          return SZ_ERROR_DATA;\n        processed = (SizeT)(p->buf - src);\n        (*srcLen) += processed;\n        src += processed;\n        inSize -= processed;\n      }\n      else\n      {\n        unsigned rem = p->tempBufSize, lookAhead = 0;\n        while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)\n          p->tempBuf[rem++] = src[lookAhead++];\n        p->tempBufSize = rem;\n        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\n        {\n          int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);\n          if (dummyRes == DUMMY_ERROR)\n          {\n            (*srcLen) += lookAhead;\n            *status = LZMA_STATUS_NEEDS_MORE_INPUT;\n            return SZ_OK;\n          }\n          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)\n          {\n            *status = LZMA_STATUS_NOT_FINISHED;\n            return SZ_ERROR_DATA;\n          }\n        }\n        p->buf = p->tempBuf;\n        if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)\n          return SZ_ERROR_DATA;\n        lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));\n        (*srcLen) += lookAhead;\n        src += lookAhead;\n        inSize -= lookAhead;\n        p->tempBufSize = 0;\n      }\n  }\n  if (p->code == 0)\n    *status = LZMA_STATUS_FINISHED_WITH_MARK;\n  return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;\n}\n\nSRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\n{\n  SizeT outSize = *destLen;\n  SizeT inSize = *srcLen;\n  *srcLen = *destLen = 0;\n  for (;;)\n  {\n    SizeT inSizeCur = inSize, outSizeCur, dicPos;\n    ELzmaFinishMode curFinishMode;\n    SRes res;\n    if (p->dicPos == p->dicBufSize)\n      p->dicPos = 0;\n    dicPos = p->dicPos;\n    if (outSize > p->dicBufSize - dicPos)\n    {\n      outSizeCur = p->dicBufSize;\n      curFinishMode = LZMA_FINISH_ANY;\n    }\n    else\n    {\n      outSizeCur = dicPos + outSize;\n      curFinishMode = finishMode;\n    }\n\n    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);\n    src += inSizeCur;\n    inSize -= inSizeCur;\n    *srcLen += inSizeCur;\n    outSizeCur = p->dicPos - dicPos;\n    memcpy(dest, p->dic + dicPos, outSizeCur);\n    dest += outSizeCur;\n    outSize -= outSizeCur;\n    *destLen += outSizeCur;\n    if (res != 0)\n      return res;\n    if (outSizeCur == 0 || outSize == 0)\n      return SZ_OK;\n  }\n}\n\nvoid LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)\n{\n  alloc->Free(alloc, p->probs);\n  p->probs = 0;\n}\n\nstatic void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)\n{\n  alloc->Free(alloc, p->dic);\n  p->dic = 0;\n}\n\nvoid LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)\n{\n  LzmaDec_FreeProbs(p, alloc);\n  LzmaDec_FreeDict(p, alloc);\n}\n\nSRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)\n{\n  UInt32 dicSize;\n  Byte d;\n\n  if (size < LZMA_PROPS_SIZE)\n    return SZ_ERROR_UNSUPPORTED;\n  else\n    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);\n\n  if (dicSize < LZMA_DIC_MIN)\n    dicSize = LZMA_DIC_MIN;\n  p->dicSize = dicSize;\n\n  d = data[0];\n  if (d >= (9 * 5 * 5))\n    return SZ_ERROR_UNSUPPORTED;\n\n  p->lc = d % 9;\n  d /= 9;\n  p->pb = d / 5;\n  p->lp = d % 5;\n\n  return SZ_OK;\n}\n\nstatic SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)\n{\n  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);\n  if (p->probs == 0 || numProbs != p->numProbs)\n  {\n    LzmaDec_FreeProbs(p, alloc);\n    p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));\n    p->numProbs = numProbs;\n    if (p->probs == 0)\n      return SZ_ERROR_MEM;\n  }\n  return SZ_OK;\n}\n\nSRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)\n{\n  CLzmaProps propNew;\n  RINOK(LzmaProps_Decode(&propNew, props, propsSize));\n  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));\n  p->prop = propNew;\n  return SZ_OK;\n}\n\nSRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)\n{\n  CLzmaProps propNew;\n  SizeT dicBufSize;\n  RINOK(LzmaProps_Decode(&propNew, props, propsSize));\n  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));\n  dicBufSize = propNew.dicSize;\n  if (p->dic == 0 || dicBufSize != p->dicBufSize)\n  {\n    LzmaDec_FreeDict(p, alloc);\n    p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);\n    if (p->dic == 0)\n    {\n      LzmaDec_FreeProbs(p, alloc);\n      return SZ_ERROR_MEM;\n    }\n  }\n  p->dicBufSize = dicBufSize;\n  p->prop = propNew;\n  return SZ_OK;\n}\n\nSRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,\n    ELzmaStatus *status, ISzAlloc *alloc)\n{\n  CLzmaDec p;\n  SRes res;\n  SizeT inSize = *srcLen;\n  SizeT outSize = *destLen;\n  *srcLen = *destLen = 0;\n  if (inSize < RC_INIT_SIZE)\n    return SZ_ERROR_INPUT_EOF;\n\n  LzmaDec_Construct(&p);\n  res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);\n  if (res != 0)\n    return res;\n  p.dic = dest;\n  p.dicBufSize = outSize;\n\n  LzmaDec_Init(&p);\n\n  *srcLen = inSize;\n  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);\n\n  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)\n    res = SZ_ERROR_INPUT_EOF;\n\n  (*destLen) = p.dicPos;\n  LzmaDec_FreeProbs(&p, alloc);\n  return res;\n}\n"
  },
  {
    "path": "src/lzma/LzmaEnc.c",
    "content": "/* LzmaEnc.c -- LZMA Encoder\n2009-11-24 : Igor Pavlov : Public domain */\n\n#include <string.h>\n\n/* #define SHOW_STAT */\n/* #define SHOW_STAT2 */\n\n#if defined(SHOW_STAT) || defined(SHOW_STAT2)\n#include <stdio.h>\n#endif\n\n#include \"lzma/LzmaEnc.h\"\n\n/* disable MT */\n#define _7ZIP_ST\n\n#include \"lzma/LzFind.h\"\n#ifndef _7ZIP_ST\n#include \"LzFindMt.h\"\n#endif\n\n#ifdef SHOW_STAT\nstatic int ttt = 0;\n#endif\n\n#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)\n\n#define kBlockSize (9 << 10)\n#define kUnpackBlockSize (1 << 18)\n#define kMatchArraySize (1 << 21)\n#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)\n\n#define kNumMaxDirectBits (31)\n\n#define kNumTopBits 24\n#define kTopValue ((UInt32)1 << kNumTopBits)\n\n#define kNumBitModelTotalBits 11\n#define kBitModelTotal (1 << kNumBitModelTotalBits)\n#define kNumMoveBits 5\n#define kProbInitValue (kBitModelTotal >> 1)\n\n#define kNumMoveReducingBits 4\n#define kNumBitPriceShiftBits 4\n#define kBitPrice (1 << kNumBitPriceShiftBits)\n\nvoid LzmaEncProps_Init(CLzmaEncProps *p)\n{\n  p->level = 5;\n  p->dictSize = p->mc = 0;\n  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;\n  p->writeEndMark = 0;\n}\n\nvoid LzmaEncProps_Normalize(CLzmaEncProps *p)\n{\n  int level = p->level;\n  if (level < 0) level = 5;\n  p->level = level;\n  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));\n  if (p->lc < 0) p->lc = 3;\n  if (p->lp < 0) p->lp = 0;\n  if (p->pb < 0) p->pb = 2;\n  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);\n  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);\n  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);\n  if (p->numHashBytes < 0) p->numHashBytes = 4;\n  if (p->mc == 0)  p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);\n  if (p->numThreads < 0)\n    p->numThreads =\n      #ifndef _7ZIP_ST\n      ((p->btMode && p->algo) ? 2 : 1);\n      #else\n      1;\n      #endif\n}\n\nUInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)\n{\n  CLzmaEncProps props = *props2;\n  LzmaEncProps_Normalize(&props);\n  return props.dictSize;\n}\n\n/* #define LZMA_LOG_BSR */\n/* Define it for Intel's CPU */\n\n\n#ifdef LZMA_LOG_BSR\n\n#define kDicLogSizeMaxCompress 30\n\n#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }\n\nUInt32 GetPosSlot1(UInt32 pos)\n{\n  UInt32 res;\n  BSR2_RET(pos, res);\n  return res;\n}\n#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }\n#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }\n\n#else\n\n#define kNumLogBits (9 + (int)sizeof(size_t) / 2)\n#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)\n\nvoid LzmaEnc_FastPosInit(Byte *g_FastPos)\n{\n  int c = 2, slotFast;\n  g_FastPos[0] = 0;\n  g_FastPos[1] = 1;\n\n  for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)\n  {\n    UInt32 k = (1 << ((slotFast >> 1) - 1));\n    UInt32 j;\n    for (j = 0; j < k; j++, c++)\n      g_FastPos[c] = (Byte)slotFast;\n  }\n}\n\n#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \\\n  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \\\n  res = p->g_FastPos[pos >> i] + (i * 2); }\n/*\n#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \\\n  p->g_FastPos[pos >> 6] + 12 : \\\n  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }\n*/\n\n#define GetPosSlot1(pos) p->g_FastPos[pos]\n#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }\n#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }\n\n#endif\n\n\n#define LZMA_NUM_REPS 4\n\ntypedef unsigned CState;\n\ntypedef struct\n{\n  UInt32 price;\n\n  CState state;\n  int prev1IsChar;\n  int prev2;\n\n  UInt32 posPrev2;\n  UInt32 backPrev2;\n\n  UInt32 posPrev;\n  UInt32 backPrev;\n  UInt32 backs[LZMA_NUM_REPS];\n} COptimal;\n\n#define kNumOpts (1 << 12)\n\n#define kNumLenToPosStates 4\n#define kNumPosSlotBits 6\n#define kDicLogSizeMin 0\n#define kDicLogSizeMax 32\n#define kDistTableSizeMax (kDicLogSizeMax * 2)\n\n\n#define kNumAlignBits 4\n#define kAlignTableSize (1 << kNumAlignBits)\n#define kAlignMask (kAlignTableSize - 1)\n\n#define kStartPosModelIndex 4\n#define kEndPosModelIndex 14\n#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)\n\n#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\n\n#ifdef _LZMA_PROB32\n#define CLzmaProb UInt32\n#else\n#define CLzmaProb UInt16\n#endif\n\n#define LZMA_PB_MAX 4\n#define LZMA_LC_MAX 8\n#define LZMA_LP_MAX 4\n\n#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)\n\n\n#define kLenNumLowBits 3\n#define kLenNumLowSymbols (1 << kLenNumLowBits)\n#define kLenNumMidBits 3\n#define kLenNumMidSymbols (1 << kLenNumMidBits)\n#define kLenNumHighBits 8\n#define kLenNumHighSymbols (1 << kLenNumHighBits)\n\n#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)\n\n#define LZMA_MATCH_LEN_MIN 2\n#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)\n\n#define kNumStates 12\n\ntypedef struct\n{\n  CLzmaProb choice;\n  CLzmaProb choice2;\n  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];\n  CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];\n  CLzmaProb high[kLenNumHighSymbols];\n} CLenEnc;\n\ntypedef struct\n{\n  CLenEnc p;\n  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];\n  UInt32 tableSize;\n  UInt32 counters[LZMA_NUM_PB_STATES_MAX];\n} CLenPriceEnc;\n\ntypedef struct\n{\n  UInt32 range;\n  Byte cache;\n  UInt64 low;\n  UInt64 cacheSize;\n  Byte *buf;\n  Byte *bufLim;\n  Byte *bufBase;\n  ISeqOutStream *outStream;\n  UInt64 processed;\n  SRes res;\n} CRangeEnc;\n\ntypedef struct\n{\n  CLzmaProb *litProbs;\n\n  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\n  CLzmaProb isRep[kNumStates];\n  CLzmaProb isRepG0[kNumStates];\n  CLzmaProb isRepG1[kNumStates];\n  CLzmaProb isRepG2[kNumStates];\n  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];\n\n  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];\n  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];\n  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\n\n  CLenPriceEnc lenEnc;\n  CLenPriceEnc repLenEnc;\n\n  UInt32 reps[LZMA_NUM_REPS];\n  UInt32 state;\n} CSaveState;\n\ntypedef struct\n{\n  IMatchFinder matchFinder;\n  void *matchFinderObj;\n\n  #ifndef _7ZIP_ST\n  Bool mtMode;\n  CMatchFinderMt matchFinderMt;\n  #endif\n\n  CMatchFinder matchFinderBase;\n\n  #ifndef _7ZIP_ST\n  Byte pad[128];\n  #endif\n\n  UInt32 optimumEndIndex;\n  UInt32 optimumCurrentIndex;\n\n  UInt32 longestMatchLength;\n  UInt32 numPairs;\n  UInt32 numAvail;\n  COptimal opt[kNumOpts];\n\n  #ifndef LZMA_LOG_BSR\n  Byte g_FastPos[1 << kNumLogBits];\n  #endif\n\n  UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];\n  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];\n  UInt32 numFastBytes;\n  UInt32 additionalOffset;\n  UInt32 reps[LZMA_NUM_REPS];\n  UInt32 state;\n\n  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];\n  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];\n  UInt32 alignPrices[kAlignTableSize];\n  UInt32 alignPriceCount;\n\n  UInt32 distTableSize;\n\n  unsigned lc, lp, pb;\n  unsigned lpMask, pbMask;\n\n  CLzmaProb *litProbs;\n\n  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\n  CLzmaProb isRep[kNumStates];\n  CLzmaProb isRepG0[kNumStates];\n  CLzmaProb isRepG1[kNumStates];\n  CLzmaProb isRepG2[kNumStates];\n  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];\n\n  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];\n  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];\n  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\n\n  CLenPriceEnc lenEnc;\n  CLenPriceEnc repLenEnc;\n\n  unsigned lclp;\n\n  Bool fastMode;\n\n  CRangeEnc rc;\n\n  Bool writeEndMark;\n  UInt64 nowPos64;\n  UInt32 matchPriceCount;\n  Bool finished;\n  Bool multiThread;\n\n  SRes result;\n  UInt32 dictSize;\n  UInt32 matchFinderCycles;\n\n  int needInit;\n\n  CSaveState saveState;\n} CLzmaEnc;\n\nvoid LzmaEnc_SaveState(CLzmaEncHandle pp)\n{\n  CLzmaEnc *p = (CLzmaEnc *)pp;\n  CSaveState *dest = &p->saveState;\n  int i;\n  dest->lenEnc = p->lenEnc;\n  dest->repLenEnc = p->repLenEnc;\n  dest->state = p->state;\n\n  for (i = 0; i < kNumStates; i++)\n  {\n    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));\n    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));\n  }\n  for (i = 0; i < kNumLenToPosStates; i++)\n    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));\n  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));\n  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));\n  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));\n  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));\n  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));\n  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));\n  memcpy(dest->reps, p->reps, sizeof(p->reps));\n  memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));\n}\n\nvoid LzmaEnc_RestoreState(CLzmaEncHandle pp)\n{\n  CLzmaEnc *dest = (CLzmaEnc *)pp;\n  const CSaveState *p = &dest->saveState;\n  int i;\n  dest->lenEnc = p->lenEnc;\n  dest->repLenEnc = p->repLenEnc;\n  dest->state = p->state;\n\n  for (i = 0; i < kNumStates; i++)\n  {\n    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));\n    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));\n  }\n  for (i = 0; i < kNumLenToPosStates; i++)\n    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));\n  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));\n  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));\n  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));\n  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));\n  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));\n  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));\n  memcpy(dest->reps, p->reps, sizeof(p->reps));\n  memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));\n}\n\nSRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)\n{\n  CLzmaEnc *p = (CLzmaEnc *)pp;\n  CLzmaEncProps props = *props2;\n  LzmaEncProps_Normalize(&props);\n\n  if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||\n      props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30))\n    return SZ_ERROR_PARAM;\n  p->dictSize = props.dictSize;\n  p->matchFinderCycles = props.mc;\n  {\n    unsigned fb = props.fb;\n    if (fb < 5)\n      fb = 5;\n    if (fb > LZMA_MATCH_LEN_MAX)\n      fb = LZMA_MATCH_LEN_MAX;\n    p->numFastBytes = fb;\n  }\n  p->lc = props.lc;\n  p->lp = props.lp;\n  p->pb = props.pb;\n  p->fastMode = (props.algo == 0);\n  p->matchFinderBase.btMode = props.btMode;\n  {\n    UInt32 numHashBytes = 4;\n    if (props.btMode)\n    {\n      if (props.numHashBytes < 2)\n        numHashBytes = 2;\n      else if (props.numHashBytes < 4)\n        numHashBytes = props.numHashBytes;\n    }\n    p->matchFinderBase.numHashBytes = numHashBytes;\n  }\n\n  p->matchFinderBase.cutValue = props.mc;\n\n  p->writeEndMark = props.writeEndMark;\n\n  #ifndef _7ZIP_ST\n  /*\n  if (newMultiThread != _multiThread)\n  {\n    ReleaseMatchFinder();\n    _multiThread = newMultiThread;\n  }\n  */\n  p->multiThread = (props.numThreads > 1);\n  #endif\n\n  return SZ_OK;\n}\n\nstatic const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};\nstatic const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};\nstatic const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};\nstatic const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};\n\n#define IsCharState(s) ((s) < 7)\n\n#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)\n\n#define kInfinityPrice (1 << 30)\n\nstatic void RangeEnc_Construct(CRangeEnc *p)\n{\n  p->outStream = 0;\n  p->bufBase = 0;\n}\n\n#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)\n\n#define RC_BUF_SIZE (1 << 16)\nstatic int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)\n{\n  if (p->bufBase == 0)\n  {\n    p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);\n    if (p->bufBase == 0)\n      return 0;\n    p->bufLim = p->bufBase + RC_BUF_SIZE;\n  }\n  return 1;\n}\n\nstatic void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)\n{\n  alloc->Free(alloc, p->bufBase);\n  p->bufBase = 0;\n}\n\nstatic void RangeEnc_Init(CRangeEnc *p)\n{\n  /* Stream.Init(); */\n  p->low = 0;\n  p->range = 0xFFFFFFFF;\n  p->cacheSize = 1;\n  p->cache = 0;\n\n  p->buf = p->bufBase;\n\n  p->processed = 0;\n  p->res = SZ_OK;\n}\n\nstatic void RangeEnc_FlushStream(CRangeEnc *p)\n{\n  size_t num;\n  if (p->res != SZ_OK)\n    return;\n  num = p->buf - p->bufBase;\n  if (num != p->outStream->Write(p->outStream, p->bufBase, num))\n    p->res = SZ_ERROR_WRITE;\n  p->processed += num;\n  p->buf = p->bufBase;\n}\n\nstatic void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)\n{\n  if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)\n  {\n    Byte temp = p->cache;\n    do\n    {\n      Byte *buf = p->buf;\n      *buf++ = (Byte)(temp + (Byte)(p->low >> 32));\n      p->buf = buf;\n      if (buf == p->bufLim)\n        RangeEnc_FlushStream(p);\n      temp = 0xFF;\n    }\n    while (--p->cacheSize != 0);\n    p->cache = (Byte)((UInt32)p->low >> 24);\n  }\n  p->cacheSize++;\n  p->low = (UInt32)p->low << 8;\n}\n\nstatic void RangeEnc_FlushData(CRangeEnc *p)\n{\n  int i;\n  for (i = 0; i < 5; i++)\n    RangeEnc_ShiftLow(p);\n}\n\nstatic void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)\n{\n  do\n  {\n    p->range >>= 1;\n    p->low += p->range & (0 - ((value >> --numBits) & 1));\n    if (p->range < kTopValue)\n    {\n      p->range <<= 8;\n      RangeEnc_ShiftLow(p);\n    }\n  }\n  while (numBits != 0);\n}\n\nstatic void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)\n{\n  UInt32 ttt = *prob;\n  UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;\n  if (symbol == 0)\n  {\n    p->range = newBound;\n    ttt += (kBitModelTotal - ttt) >> kNumMoveBits;\n  }\n  else\n  {\n    p->low += newBound;\n    p->range -= newBound;\n    ttt -= ttt >> kNumMoveBits;\n  }\n  *prob = (CLzmaProb)ttt;\n  if (p->range < kTopValue)\n  {\n    p->range <<= 8;\n    RangeEnc_ShiftLow(p);\n  }\n}\n\nstatic void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)\n{\n  symbol |= 0x100;\n  do\n  {\n    RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);\n    symbol <<= 1;\n  }\n  while (symbol < 0x10000);\n}\n\nstatic void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)\n{\n  UInt32 offs = 0x100;\n  symbol |= 0x100;\n  do\n  {\n    matchByte <<= 1;\n    RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);\n    symbol <<= 1;\n    offs &= ~(matchByte ^ symbol);\n  }\n  while (symbol < 0x10000);\n}\n\nvoid LzmaEnc_InitPriceTables(UInt32 *ProbPrices)\n{\n  UInt32 i;\n  for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))\n  {\n    const int kCyclesBits = kNumBitPriceShiftBits;\n    UInt32 w = i;\n    UInt32 bitCount = 0;\n    int j;\n    for (j = 0; j < kCyclesBits; j++)\n    {\n      w = w * w;\n      bitCount <<= 1;\n      while (w >= ((UInt32)1 << 16))\n      {\n        w >>= 1;\n        bitCount++;\n      }\n    }\n    ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);\n  }\n}\n\n\n#define GET_PRICE(prob, symbol) \\\n  p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];\n\n#define GET_PRICEa(prob, symbol) \\\n  ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];\n\n#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]\n#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]\n\n#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]\n#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]\n\nstatic UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)\n{\n  UInt32 price = 0;\n  symbol |= 0x100;\n  do\n  {\n    price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);\n    symbol <<= 1;\n  }\n  while (symbol < 0x10000);\n  return price;\n}\n\nstatic UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)\n{\n  UInt32 price = 0;\n  UInt32 offs = 0x100;\n  symbol |= 0x100;\n  do\n  {\n    matchByte <<= 1;\n    price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);\n    symbol <<= 1;\n    offs &= ~(matchByte ^ symbol);\n  }\n  while (symbol < 0x10000);\n  return price;\n}\n\n\nstatic void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)\n{\n  UInt32 m = 1;\n  int i;\n  for (i = numBitLevels; i != 0;)\n  {\n    UInt32 bit;\n    i--;\n    bit = (symbol >> i) & 1;\n    RangeEnc_EncodeBit(rc, probs + m, bit);\n    m = (m << 1) | bit;\n  }\n}\n\nstatic void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)\n{\n  UInt32 m = 1;\n  int i;\n  for (i = 0; i < numBitLevels; i++)\n  {\n    UInt32 bit = symbol & 1;\n    RangeEnc_EncodeBit(rc, probs + m, bit);\n    m = (m << 1) | bit;\n    symbol >>= 1;\n  }\n}\n\nstatic UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)\n{\n  UInt32 price = 0;\n  symbol |= (1 << numBitLevels);\n  while (symbol != 1)\n  {\n    price += GET_PRICEa(probs[symbol >> 1], symbol & 1);\n    symbol >>= 1;\n  }\n  return price;\n}\n\nstatic UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)\n{\n  UInt32 price = 0;\n  UInt32 m = 1;\n  int i;\n  for (i = numBitLevels; i != 0; i--)\n  {\n    UInt32 bit = symbol & 1;\n    symbol >>= 1;\n    price += GET_PRICEa(probs[m], bit);\n    m = (m << 1) | bit;\n  }\n  return price;\n}\n\n\nstatic void LenEnc_Init(CLenEnc *p)\n{\n  unsigned i;\n  p->choice = p->choice2 = kProbInitValue;\n  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)\n    p->low[i] = kProbInitValue;\n  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)\n    p->mid[i] = kProbInitValue;\n  for (i = 0; i < kLenNumHighSymbols; i++)\n    p->high[i] = kProbInitValue;\n}\n\nstatic void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)\n{\n  if (symbol < kLenNumLowSymbols)\n  {\n    RangeEnc_EncodeBit(rc, &p->choice, 0);\n    RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);\n  }\n  else\n  {\n    RangeEnc_EncodeBit(rc, &p->choice, 1);\n    if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)\n    {\n      RangeEnc_EncodeBit(rc, &p->choice2, 0);\n      RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);\n    }\n    else\n    {\n      RangeEnc_EncodeBit(rc, &p->choice2, 1);\n      RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);\n    }\n  }\n}\n\nstatic void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)\n{\n  UInt32 a0 = GET_PRICE_0a(p->choice);\n  UInt32 a1 = GET_PRICE_1a(p->choice);\n  UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);\n  UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);\n  UInt32 i = 0;\n  for (i = 0; i < kLenNumLowSymbols; i++)\n  {\n    if (i >= numSymbols)\n      return;\n    prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);\n  }\n  for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)\n  {\n    if (i >= numSymbols)\n      return;\n    prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);\n  }\n  for (; i < numSymbols; i++)\n    prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);\n}\n\nstatic void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)\n{\n  LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);\n  p->counters[posState] = p->tableSize;\n}\n\nstatic void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)\n{\n  UInt32 posState;\n  for (posState = 0; posState < numPosStates; posState++)\n    LenPriceEnc_UpdateTable(p, posState, ProbPrices);\n}\n\nstatic void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)\n{\n  LenEnc_Encode(&p->p, rc, symbol, posState);\n  if (updatePrice)\n    if (--p->counters[posState] == 0)\n      LenPriceEnc_UpdateTable(p, posState, ProbPrices);\n}\n\n\n\n\nstatic void MovePos(CLzmaEnc *p, UInt32 num)\n{\n  #ifdef SHOW_STAT\n  ttt += num;\n  printf(\"\\n MovePos %d\", num);\n  #endif\n  if (num != 0)\n  {\n    p->additionalOffset += num;\n    p->matchFinder.Skip(p->matchFinderObj, num);\n  }\n}\n\nstatic UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)\n{\n  UInt32 lenRes = 0, numPairs;\n  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);\n  numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);\n  #ifdef SHOW_STAT\n  printf(\"\\n i = %d numPairs = %d    \", ttt, numPairs / 2);\n  ttt++;\n  {\n    UInt32 i;\n    for (i = 0; i < numPairs; i += 2)\n      printf(\"%2d %6d   | \", p->matches[i], p->matches[i + 1]);\n  }\n  #endif\n  if (numPairs > 0)\n  {\n    lenRes = p->matches[numPairs - 2];\n    if (lenRes == p->numFastBytes)\n    {\n      const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n      UInt32 distance = p->matches[numPairs - 1] + 1;\n      UInt32 numAvail = p->numAvail;\n      if (numAvail > LZMA_MATCH_LEN_MAX)\n        numAvail = LZMA_MATCH_LEN_MAX;\n      {\n        const Byte *pby2 = pby - distance;\n        for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);\n      }\n    }\n  }\n  p->additionalOffset++;\n  *numDistancePairsRes = numPairs;\n  return lenRes;\n}\n\n\n#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;\n#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;\n#define IsShortRep(p) ((p)->backPrev == 0)\n\nstatic UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)\n{\n  return\n    GET_PRICE_0(p->isRepG0[state]) +\n    GET_PRICE_0(p->isRep0Long[state][posState]);\n}\n\nstatic UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)\n{\n  UInt32 price;\n  if (repIndex == 0)\n  {\n    price = GET_PRICE_0(p->isRepG0[state]);\n    price += GET_PRICE_1(p->isRep0Long[state][posState]);\n  }\n  else\n  {\n    price = GET_PRICE_1(p->isRepG0[state]);\n    if (repIndex == 1)\n      price += GET_PRICE_0(p->isRepG1[state]);\n    else\n    {\n      price += GET_PRICE_1(p->isRepG1[state]);\n      price += GET_PRICE(p->isRepG2[state], repIndex - 2);\n    }\n  }\n  return price;\n}\n\nstatic UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)\n{\n  return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +\n    GetPureRepPrice(p, repIndex, state, posState);\n}\n\nstatic UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)\n{\n  UInt32 posMem = p->opt[cur].posPrev;\n  UInt32 backMem = p->opt[cur].backPrev;\n  p->optimumEndIndex = cur;\n  do\n  {\n    if (p->opt[cur].prev1IsChar)\n    {\n      MakeAsChar(&p->opt[posMem])\n      p->opt[posMem].posPrev = posMem - 1;\n      if (p->opt[cur].prev2)\n      {\n        p->opt[posMem - 1].prev1IsChar = False;\n        p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;\n        p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;\n      }\n    }\n    {\n      UInt32 posPrev = posMem;\n      UInt32 backCur = backMem;\n\n      backMem = p->opt[posPrev].backPrev;\n      posMem = p->opt[posPrev].posPrev;\n\n      p->opt[posPrev].backPrev = backCur;\n      p->opt[posPrev].posPrev = cur;\n      cur = posPrev;\n    }\n  }\n  while (cur != 0);\n  *backRes = p->opt[0].backPrev;\n  p->optimumCurrentIndex  = p->opt[0].posPrev;\n  return p->optimumCurrentIndex;\n}\n\n#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)\n\nstatic UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)\n{\n  UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;\n  UInt32 matchPrice, repMatchPrice, normalMatchPrice;\n  UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];\n  UInt32 *matches;\n  const Byte *data;\n  Byte curByte, matchByte;\n  if (p->optimumEndIndex != p->optimumCurrentIndex)\n  {\n    const COptimal *opt = &p->opt[p->optimumCurrentIndex];\n    UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;\n    *backRes = opt->backPrev;\n    p->optimumCurrentIndex = opt->posPrev;\n    return lenRes;\n  }\n  p->optimumCurrentIndex = p->optimumEndIndex = 0;\n\n  if (p->additionalOffset == 0)\n    mainLen = ReadMatchDistances(p, &numPairs);\n  else\n  {\n    mainLen = p->longestMatchLength;\n    numPairs = p->numPairs;\n  }\n\n  numAvail = p->numAvail;\n  if (numAvail < 2)\n  {\n    *backRes = (UInt32)(-1);\n    return 1;\n  }\n  if (numAvail > LZMA_MATCH_LEN_MAX)\n    numAvail = LZMA_MATCH_LEN_MAX;\n\n  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n  repMaxIndex = 0;\n  for (i = 0; i < LZMA_NUM_REPS; i++)\n  {\n    UInt32 lenTest;\n    const Byte *data2;\n    reps[i] = p->reps[i];\n    data2 = data - (reps[i] + 1);\n    if (data[0] != data2[0] || data[1] != data2[1])\n    {\n      repLens[i] = 0;\n      continue;\n    }\n    for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);\n    repLens[i] = lenTest;\n    if (lenTest > repLens[repMaxIndex])\n      repMaxIndex = i;\n  }\n  if (repLens[repMaxIndex] >= p->numFastBytes)\n  {\n    UInt32 lenRes;\n    *backRes = repMaxIndex;\n    lenRes = repLens[repMaxIndex];\n    MovePos(p, lenRes - 1);\n    return lenRes;\n  }\n\n  matches = p->matches;\n  if (mainLen >= p->numFastBytes)\n  {\n    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;\n    MovePos(p, mainLen - 1);\n    return mainLen;\n  }\n  curByte = *data;\n  matchByte = *(data - (reps[0] + 1));\n\n  if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)\n  {\n    *backRes = (UInt32)-1;\n    return 1;\n  }\n\n  p->opt[0].state = (CState)p->state;\n\n  posState = (position & p->pbMask);\n\n  {\n    const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\n    p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +\n        (!IsCharState(p->state) ?\n          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :\n          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\n  }\n\n  MakeAsChar(&p->opt[1]);\n\n  matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);\n  repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);\n\n  if (matchByte == curByte)\n  {\n    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);\n    if (shortRepPrice < p->opt[1].price)\n    {\n      p->opt[1].price = shortRepPrice;\n      MakeAsShortRep(&p->opt[1]);\n    }\n  }\n  lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);\n\n  if (lenEnd < 2)\n  {\n    *backRes = p->opt[1].backPrev;\n    return 1;\n  }\n\n  p->opt[1].posPrev = 0;\n  for (i = 0; i < LZMA_NUM_REPS; i++)\n    p->opt[0].backs[i] = reps[i];\n\n  len = lenEnd;\n  do\n    p->opt[len--].price = kInfinityPrice;\n  while (len >= 2);\n\n  for (i = 0; i < LZMA_NUM_REPS; i++)\n  {\n    UInt32 repLen = repLens[i];\n    UInt32 price;\n    if (repLen < 2)\n      continue;\n    price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);\n    do\n    {\n      UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];\n      COptimal *opt = &p->opt[repLen];\n      if (curAndLenPrice < opt->price)\n      {\n        opt->price = curAndLenPrice;\n        opt->posPrev = 0;\n        opt->backPrev = i;\n        opt->prev1IsChar = False;\n      }\n    }\n    while (--repLen >= 2);\n  }\n\n  normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);\n\n  len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);\n  if (len <= mainLen)\n  {\n    UInt32 offs = 0;\n    while (len > matches[offs])\n      offs += 2;\n    for (; ; len++)\n    {\n      COptimal *opt;\n      UInt32 distance = matches[offs + 1];\n\n      UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];\n      UInt32 lenToPosState = GetLenToPosState(len);\n      if (distance < kNumFullDistances)\n        curAndLenPrice += p->distancesPrices[lenToPosState][distance];\n      else\n      {\n        UInt32 slot;\n        GetPosSlot2(distance, slot);\n        curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];\n      }\n      opt = &p->opt[len];\n      if (curAndLenPrice < opt->price)\n      {\n        opt->price = curAndLenPrice;\n        opt->posPrev = 0;\n        opt->backPrev = distance + LZMA_NUM_REPS;\n        opt->prev1IsChar = False;\n      }\n      if (len == matches[offs])\n      {\n        offs += 2;\n        if (offs == numPairs)\n          break;\n      }\n    }\n  }\n\n  cur = 0;\n\n    #ifdef SHOW_STAT2\n    if (position >= 0)\n    {\n      unsigned i;\n      printf(\"\\n pos = %4X\", position);\n      for (i = cur; i <= lenEnd; i++)\n      printf(\"\\nprice[%4X] = %d\", position - cur + i, p->opt[i].price);\n    }\n    #endif\n\n  for (;;)\n  {\n    UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;\n    UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;\n    Bool nextIsChar;\n    Byte curByte, matchByte;\n    const Byte *data;\n    COptimal *curOpt;\n    COptimal *nextOpt;\n\n    cur++;\n    if (cur == lenEnd)\n      return Backward(p, backRes, cur);\n\n    newLen = ReadMatchDistances(p, &numPairs);\n    if (newLen >= p->numFastBytes)\n    {\n      p->numPairs = numPairs;\n      p->longestMatchLength = newLen;\n      return Backward(p, backRes, cur);\n    }\n    position++;\n    curOpt = &p->opt[cur];\n    posPrev = curOpt->posPrev;\n    if (curOpt->prev1IsChar)\n    {\n      posPrev--;\n      if (curOpt->prev2)\n      {\n        state = p->opt[curOpt->posPrev2].state;\n        if (curOpt->backPrev2 < LZMA_NUM_REPS)\n          state = kRepNextStates[state];\n        else\n          state = kMatchNextStates[state];\n      }\n      else\n        state = p->opt[posPrev].state;\n      state = kLiteralNextStates[state];\n    }\n    else\n      state = p->opt[posPrev].state;\n    if (posPrev == cur - 1)\n    {\n      if (IsShortRep(curOpt))\n        state = kShortRepNextStates[state];\n      else\n        state = kLiteralNextStates[state];\n    }\n    else\n    {\n      UInt32 pos;\n      const COptimal *prevOpt;\n      if (curOpt->prev1IsChar && curOpt->prev2)\n      {\n        posPrev = curOpt->posPrev2;\n        pos = curOpt->backPrev2;\n        state = kRepNextStates[state];\n      }\n      else\n      {\n        pos = curOpt->backPrev;\n        if (pos < LZMA_NUM_REPS)\n          state = kRepNextStates[state];\n        else\n          state = kMatchNextStates[state];\n      }\n      prevOpt = &p->opt[posPrev];\n      if (pos < LZMA_NUM_REPS)\n      {\n        UInt32 i;\n        reps[0] = prevOpt->backs[pos];\n        for (i = 1; i <= pos; i++)\n          reps[i] = prevOpt->backs[i - 1];\n        for (; i < LZMA_NUM_REPS; i++)\n          reps[i] = prevOpt->backs[i];\n      }\n      else\n      {\n        UInt32 i;\n        reps[0] = (pos - LZMA_NUM_REPS);\n        for (i = 1; i < LZMA_NUM_REPS; i++)\n          reps[i] = prevOpt->backs[i - 1];\n      }\n    }\n    curOpt->state = (CState)state;\n\n    curOpt->backs[0] = reps[0];\n    curOpt->backs[1] = reps[1];\n    curOpt->backs[2] = reps[2];\n    curOpt->backs[3] = reps[3];\n\n    curPrice = curOpt->price;\n    nextIsChar = False;\n    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n    curByte = *data;\n    matchByte = *(data - (reps[0] + 1));\n\n    posState = (position & p->pbMask);\n\n    curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);\n    {\n      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\n      curAnd1Price +=\n        (!IsCharState(state) ?\n          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :\n          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\n    }\n\n    nextOpt = &p->opt[cur + 1];\n\n    if (curAnd1Price < nextOpt->price)\n    {\n      nextOpt->price = curAnd1Price;\n      nextOpt->posPrev = cur;\n      MakeAsChar(nextOpt);\n      nextIsChar = True;\n    }\n\n    matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);\n    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);\n\n    if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))\n    {\n      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);\n      if (shortRepPrice <= nextOpt->price)\n      {\n        nextOpt->price = shortRepPrice;\n        nextOpt->posPrev = cur;\n        MakeAsShortRep(nextOpt);\n        nextIsChar = True;\n      }\n    }\n    numAvailFull = p->numAvail;\n    {\n      UInt32 temp = kNumOpts - 1 - cur;\n      if (temp < numAvailFull)\n        numAvailFull = temp;\n    }\n\n    if (numAvailFull < 2)\n      continue;\n    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);\n\n    if (!nextIsChar && matchByte != curByte) /* speed optimization */\n    {\n      /* try Literal + rep0 */\n      UInt32 temp;\n      UInt32 lenTest2;\n      const Byte *data2 = data - (reps[0] + 1);\n      UInt32 limit = p->numFastBytes + 1;\n      if (limit > numAvailFull)\n        limit = numAvailFull;\n\n      for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);\n      lenTest2 = temp - 1;\n      if (lenTest2 >= 2)\n      {\n        UInt32 state2 = kLiteralNextStates[state];\n        UInt32 posStateNext = (position + 1) & p->pbMask;\n        UInt32 nextRepMatchPrice = curAnd1Price +\n            GET_PRICE_1(p->isMatch[state2][posStateNext]) +\n            GET_PRICE_1(p->isRep[state2]);\n        /* for (; lenTest2 >= 2; lenTest2--) */\n        {\n          UInt32 curAndLenPrice;\n          COptimal *opt;\n          UInt32 offset = cur + 1 + lenTest2;\n          while (lenEnd < offset)\n            p->opt[++lenEnd].price = kInfinityPrice;\n          curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);\n          opt = &p->opt[offset];\n          if (curAndLenPrice < opt->price)\n          {\n            opt->price = curAndLenPrice;\n            opt->posPrev = cur + 1;\n            opt->backPrev = 0;\n            opt->prev1IsChar = True;\n            opt->prev2 = False;\n          }\n        }\n      }\n    }\n\n    startLen = 2; /* speed optimization */\n    {\n    UInt32 repIndex;\n    for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)\n    {\n      UInt32 lenTest;\n      UInt32 lenTestTemp;\n      UInt32 price;\n      const Byte *data2 = data - (reps[repIndex] + 1);\n      if (data[0] != data2[0] || data[1] != data2[1])\n        continue;\n      for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);\n      while (lenEnd < cur + lenTest)\n        p->opt[++lenEnd].price = kInfinityPrice;\n      lenTestTemp = lenTest;\n      price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);\n      do\n      {\n        UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];\n        COptimal *opt = &p->opt[cur + lenTest];\n        if (curAndLenPrice < opt->price)\n        {\n          opt->price = curAndLenPrice;\n          opt->posPrev = cur;\n          opt->backPrev = repIndex;\n          opt->prev1IsChar = False;\n        }\n      }\n      while (--lenTest >= 2);\n      lenTest = lenTestTemp;\n\n      if (repIndex == 0)\n        startLen = lenTest + 1;\n\n      /* if (_maxMode) */\n        {\n          UInt32 lenTest2 = lenTest + 1;\n          UInt32 limit = lenTest2 + p->numFastBytes;\n          UInt32 nextRepMatchPrice;\n          if (limit > numAvailFull)\n            limit = numAvailFull;\n          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);\n          lenTest2 -= lenTest + 1;\n          if (lenTest2 >= 2)\n          {\n            UInt32 state2 = kRepNextStates[state];\n            UInt32 posStateNext = (position + lenTest) & p->pbMask;\n            UInt32 curAndLenCharPrice =\n                price + p->repLenEnc.prices[posState][lenTest - 2] +\n                GET_PRICE_0(p->isMatch[state2][posStateNext]) +\n                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),\n                    data[lenTest], data2[lenTest], p->ProbPrices);\n            state2 = kLiteralNextStates[state2];\n            posStateNext = (position + lenTest + 1) & p->pbMask;\n            nextRepMatchPrice = curAndLenCharPrice +\n                GET_PRICE_1(p->isMatch[state2][posStateNext]) +\n                GET_PRICE_1(p->isRep[state2]);\n\n            /* for (; lenTest2 >= 2; lenTest2--) */\n            {\n              UInt32 curAndLenPrice;\n              COptimal *opt;\n              UInt32 offset = cur + lenTest + 1 + lenTest2;\n              while (lenEnd < offset)\n                p->opt[++lenEnd].price = kInfinityPrice;\n              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);\n              opt = &p->opt[offset];\n              if (curAndLenPrice < opt->price)\n              {\n                opt->price = curAndLenPrice;\n                opt->posPrev = cur + lenTest + 1;\n                opt->backPrev = 0;\n                opt->prev1IsChar = True;\n                opt->prev2 = True;\n                opt->posPrev2 = cur;\n                opt->backPrev2 = repIndex;\n              }\n            }\n          }\n        }\n    }\n    }\n    /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */\n    if (newLen > numAvail)\n    {\n      newLen = numAvail;\n      for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);\n      matches[numPairs] = newLen;\n      numPairs += 2;\n    }\n    if (newLen >= startLen)\n    {\n      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);\n      UInt32 offs, curBack, posSlot;\n      UInt32 lenTest;\n      while (lenEnd < cur + newLen)\n        p->opt[++lenEnd].price = kInfinityPrice;\n\n      offs = 0;\n      while (startLen > matches[offs])\n        offs += 2;\n      curBack = matches[offs + 1];\n      GetPosSlot2(curBack, posSlot);\n      for (lenTest = /*2*/ startLen; ; lenTest++)\n      {\n        UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];\n        UInt32 lenToPosState = GetLenToPosState(lenTest);\n        COptimal *opt;\n        if (curBack < kNumFullDistances)\n          curAndLenPrice += p->distancesPrices[lenToPosState][curBack];\n        else\n          curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];\n\n        opt = &p->opt[cur + lenTest];\n        if (curAndLenPrice < opt->price)\n        {\n          opt->price = curAndLenPrice;\n          opt->posPrev = cur;\n          opt->backPrev = curBack + LZMA_NUM_REPS;\n          opt->prev1IsChar = False;\n        }\n\n        if (/*_maxMode && */lenTest == matches[offs])\n        {\n          /* Try Match + Literal + Rep0 */\n          const Byte *data2 = data - (curBack + 1);\n          UInt32 lenTest2 = lenTest + 1;\n          UInt32 limit = lenTest2 + p->numFastBytes;\n          UInt32 nextRepMatchPrice;\n          if (limit > numAvailFull)\n            limit = numAvailFull;\n          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);\n          lenTest2 -= lenTest + 1;\n          if (lenTest2 >= 2)\n          {\n            UInt32 state2 = kMatchNextStates[state];\n            UInt32 posStateNext = (position + lenTest) & p->pbMask;\n            UInt32 curAndLenCharPrice = curAndLenPrice +\n                GET_PRICE_0(p->isMatch[state2][posStateNext]) +\n                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),\n                    data[lenTest], data2[lenTest], p->ProbPrices);\n            state2 = kLiteralNextStates[state2];\n            posStateNext = (posStateNext + 1) & p->pbMask;\n            nextRepMatchPrice = curAndLenCharPrice +\n                GET_PRICE_1(p->isMatch[state2][posStateNext]) +\n                GET_PRICE_1(p->isRep[state2]);\n\n            /* for (; lenTest2 >= 2; lenTest2--) */\n            {\n              UInt32 offset = cur + lenTest + 1 + lenTest2;\n              UInt32 curAndLenPrice;\n              COptimal *opt;\n              while (lenEnd < offset)\n                p->opt[++lenEnd].price = kInfinityPrice;\n              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);\n              opt = &p->opt[offset];\n              if (curAndLenPrice < opt->price)\n              {\n                opt->price = curAndLenPrice;\n                opt->posPrev = cur + lenTest + 1;\n                opt->backPrev = 0;\n                opt->prev1IsChar = True;\n                opt->prev2 = True;\n                opt->posPrev2 = cur;\n                opt->backPrev2 = curBack + LZMA_NUM_REPS;\n              }\n            }\n          }\n          offs += 2;\n          if (offs == numPairs)\n            break;\n          curBack = matches[offs + 1];\n          if (curBack >= kNumFullDistances)\n            GetPosSlot2(curBack, posSlot);\n        }\n      }\n    }\n  }\n}\n\n#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))\n\nstatic UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)\n{\n  UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;\n  const Byte *data;\n  const UInt32 *matches;\n\n  if (p->additionalOffset == 0)\n    mainLen = ReadMatchDistances(p, &numPairs);\n  else\n  {\n    mainLen = p->longestMatchLength;\n    numPairs = p->numPairs;\n  }\n\n  numAvail = p->numAvail;\n  *backRes = (UInt32)-1;\n  if (numAvail < 2)\n    return 1;\n  if (numAvail > LZMA_MATCH_LEN_MAX)\n    numAvail = LZMA_MATCH_LEN_MAX;\n  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n\n  repLen = repIndex = 0;\n  for (i = 0; i < LZMA_NUM_REPS; i++)\n  {\n    UInt32 len;\n    const Byte *data2 = data - (p->reps[i] + 1);\n    if (data[0] != data2[0] || data[1] != data2[1])\n      continue;\n    for (len = 2; len < numAvail && data[len] == data2[len]; len++);\n    if (len >= p->numFastBytes)\n    {\n      *backRes = i;\n      MovePos(p, len - 1);\n      return len;\n    }\n    if (len > repLen)\n    {\n      repIndex = i;\n      repLen = len;\n    }\n  }\n\n  matches = p->matches;\n  if (mainLen >= p->numFastBytes)\n  {\n    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;\n    MovePos(p, mainLen - 1);\n    return mainLen;\n  }\n\n  mainDist = 0; /* for GCC */\n  if (mainLen >= 2)\n  {\n    mainDist = matches[numPairs - 1];\n    while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)\n    {\n      if (!ChangePair(matches[numPairs - 3], mainDist))\n        break;\n      numPairs -= 2;\n      mainLen = matches[numPairs - 2];\n      mainDist = matches[numPairs - 1];\n    }\n    if (mainLen == 2 && mainDist >= 0x80)\n      mainLen = 1;\n  }\n\n  if (repLen >= 2 && (\n        (repLen + 1 >= mainLen) ||\n        (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||\n        (repLen + 3 >= mainLen && mainDist >= (1 << 15))))\n  {\n    *backRes = repIndex;\n    MovePos(p, repLen - 1);\n    return repLen;\n  }\n\n  if (mainLen < 2 || numAvail <= 2)\n    return 1;\n\n  p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);\n  if (p->longestMatchLength >= 2)\n  {\n    UInt32 newDistance = matches[p->numPairs - 1];\n    if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||\n        (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||\n        (p->longestMatchLength > mainLen + 1) ||\n        (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))\n      return 1;\n  }\n\n  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n  for (i = 0; i < LZMA_NUM_REPS; i++)\n  {\n    UInt32 len, limit;\n    const Byte *data2 = data - (p->reps[i] + 1);\n    if (data[0] != data2[0] || data[1] != data2[1])\n      continue;\n    limit = mainLen - 1;\n    for (len = 2; len < limit && data[len] == data2[len]; len++);\n    if (len >= limit)\n      return 1;\n  }\n  *backRes = mainDist + LZMA_NUM_REPS;\n  MovePos(p, mainLen - 2);\n  return mainLen;\n}\n\nstatic void WriteEndMarker(CLzmaEnc *p, UInt32 posState)\n{\n  UInt32 len;\n  RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);\n  RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);\n  p->state = kMatchNextStates[p->state];\n  len = LZMA_MATCH_LEN_MIN;\n  LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);\n  RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);\n  RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);\n  RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);\n}\n\nstatic SRes CheckErrors(CLzmaEnc *p)\n{\n  if (p->result != SZ_OK)\n    return p->result;\n  if (p->rc.res != SZ_OK)\n    p->result = SZ_ERROR_WRITE;\n  if (p->matchFinderBase.result != SZ_OK)\n    p->result = SZ_ERROR_READ;\n  if (p->result != SZ_OK)\n    p->finished = True;\n  return p->result;\n}\n\nstatic SRes Flush(CLzmaEnc *p, UInt32 nowPos)\n{\n  /* ReleaseMFStream(); */\n  p->finished = True;\n  if (p->writeEndMark)\n    WriteEndMarker(p, nowPos & p->pbMask);\n  RangeEnc_FlushData(&p->rc);\n  RangeEnc_FlushStream(&p->rc);\n  return CheckErrors(p);\n}\n\nstatic void FillAlignPrices(CLzmaEnc *p)\n{\n  UInt32 i;\n  for (i = 0; i < kAlignTableSize; i++)\n    p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);\n  p->alignPriceCount = 0;\n}\n\nstatic void FillDistancesPrices(CLzmaEnc *p)\n{\n  UInt32 tempPrices[kNumFullDistances];\n  UInt32 i, lenToPosState;\n  for (i = kStartPosModelIndex; i < kNumFullDistances; i++)\n  {\n    UInt32 posSlot = GetPosSlot1(i);\n    UInt32 footerBits = ((posSlot >> 1) - 1);\n    UInt32 base = ((2 | (posSlot & 1)) << footerBits);\n    tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);\n  }\n\n  for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)\n  {\n    UInt32 posSlot;\n    const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];\n    UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];\n    for (posSlot = 0; posSlot < p->distTableSize; posSlot++)\n      posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);\n    for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)\n      posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);\n\n    {\n      UInt32 *distancesPrices = p->distancesPrices[lenToPosState];\n      UInt32 i;\n      for (i = 0; i < kStartPosModelIndex; i++)\n        distancesPrices[i] = posSlotPrices[i];\n      for (; i < kNumFullDistances; i++)\n        distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];\n    }\n  }\n  p->matchPriceCount = 0;\n}\n\nvoid LzmaEnc_Construct(CLzmaEnc *p)\n{\n  RangeEnc_Construct(&p->rc);\n  MatchFinder_Construct(&p->matchFinderBase);\n  #ifndef _7ZIP_ST\n  MatchFinderMt_Construct(&p->matchFinderMt);\n  p->matchFinderMt.MatchFinder = &p->matchFinderBase;\n  #endif\n\n  {\n    CLzmaEncProps props;\n    LzmaEncProps_Init(&props);\n    LzmaEnc_SetProps(p, &props);\n  }\n\n  #ifndef LZMA_LOG_BSR\n  LzmaEnc_FastPosInit(p->g_FastPos);\n  #endif\n\n  LzmaEnc_InitPriceTables(p->ProbPrices);\n  p->litProbs = 0;\n  p->saveState.litProbs = 0;\n}\n\nCLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)\n{\n  void *p;\n  p = alloc->Alloc(alloc, sizeof(CLzmaEnc));\n  if (p != 0)\n    LzmaEnc_Construct((CLzmaEnc *)p);\n  return p;\n}\n\nvoid LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)\n{\n  alloc->Free(alloc, p->litProbs);\n  alloc->Free(alloc, p->saveState.litProbs);\n  p->litProbs = 0;\n  p->saveState.litProbs = 0;\n}\n\nvoid LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  #ifndef _7ZIP_ST\n  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);\n  #endif\n  MatchFinder_Free(&p->matchFinderBase, allocBig);\n  LzmaEnc_FreeLits(p, alloc);\n  RangeEnc_Free(&p->rc, alloc);\n}\n\nvoid LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);\n  alloc->Free(alloc, p);\n}\n\nstatic SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)\n{\n  UInt32 nowPos32, startPos32;\n  if (p->needInit)\n  {\n    p->matchFinder.Init(p->matchFinderObj);\n    p->needInit = 0;\n  }\n\n  if (p->finished)\n    return p->result;\n  RINOK(CheckErrors(p));\n\n  nowPos32 = (UInt32)p->nowPos64;\n  startPos32 = nowPos32;\n\n  if (p->nowPos64 == 0)\n  {\n    UInt32 numPairs;\n    Byte curByte;\n    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\n      return Flush(p, nowPos32);\n    ReadMatchDistances(p, &numPairs);\n    RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);\n    p->state = kLiteralNextStates[p->state];\n    curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);\n    LitEnc_Encode(&p->rc, p->litProbs, curByte);\n    p->additionalOffset--;\n    nowPos32++;\n  }\n\n  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)\n  for (;;)\n  {\n    UInt32 pos, len, posState;\n\n    if (p->fastMode)\n      len = GetOptimumFast(p, &pos);\n    else\n      len = GetOptimum(p, nowPos32, &pos);\n\n    #ifdef SHOW_STAT2\n    printf(\"\\n pos = %4X,   len = %d   pos = %d\", nowPos32, len, pos);\n    #endif\n\n    posState = nowPos32 & p->pbMask;\n    if (len == 1 && pos == (UInt32)-1)\n    {\n      Byte curByte;\n      CLzmaProb *probs;\n      const Byte *data;\n\n      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);\n      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;\n      curByte = *data;\n      probs = LIT_PROBS(nowPos32, *(data - 1));\n      if (IsCharState(p->state))\n        LitEnc_Encode(&p->rc, probs, curByte);\n      else\n        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));\n      p->state = kLiteralNextStates[p->state];\n    }\n    else\n    {\n      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);\n      if (pos < LZMA_NUM_REPS)\n      {\n        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);\n        if (pos == 0)\n        {\n          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);\n          RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));\n        }\n        else\n        {\n          UInt32 distance = p->reps[pos];\n          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);\n          if (pos == 1)\n            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);\n          else\n          {\n            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);\n            RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);\n            if (pos == 3)\n              p->reps[3] = p->reps[2];\n            p->reps[2] = p->reps[1];\n          }\n          p->reps[1] = p->reps[0];\n          p->reps[0] = distance;\n        }\n        if (len == 1)\n          p->state = kShortRepNextStates[p->state];\n        else\n        {\n          LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);\n          p->state = kRepNextStates[p->state];\n        }\n      }\n      else\n      {\n        UInt32 posSlot;\n        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);\n        p->state = kMatchNextStates[p->state];\n        LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);\n        pos -= LZMA_NUM_REPS;\n        GetPosSlot(pos, posSlot);\n        RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);\n\n        if (posSlot >= kStartPosModelIndex)\n        {\n          UInt32 footerBits = ((posSlot >> 1) - 1);\n          UInt32 base = ((2 | (posSlot & 1)) << footerBits);\n          UInt32 posReduced = pos - base;\n\n          if (posSlot < kEndPosModelIndex)\n            RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);\n          else\n          {\n            RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);\n            RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);\n            p->alignPriceCount++;\n          }\n        }\n        p->reps[3] = p->reps[2];\n        p->reps[2] = p->reps[1];\n        p->reps[1] = p->reps[0];\n        p->reps[0] = pos;\n        p->matchPriceCount++;\n      }\n    }\n    p->additionalOffset -= len;\n    nowPos32 += len;\n    if (p->additionalOffset == 0)\n    {\n      UInt32 processed;\n      if (!p->fastMode)\n      {\n        if (p->matchPriceCount >= (1 << 7))\n          FillDistancesPrices(p);\n        if (p->alignPriceCount >= kAlignTableSize)\n          FillAlignPrices(p);\n      }\n      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\n        break;\n      processed = nowPos32 - startPos32;\n      if (useLimits)\n      {\n        if (processed + kNumOpts + 300 >= maxUnpackSize ||\n            RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)\n          break;\n      }\n      else if (processed >= (1 << 15))\n      {\n        p->nowPos64 += nowPos32 - startPos32;\n        return CheckErrors(p);\n      }\n    }\n  }\n  p->nowPos64 += nowPos32 - startPos32;\n  return Flush(p, nowPos32);\n}\n\n#define kBigHashDicLimit ((UInt32)1 << 24)\n\nstatic SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  UInt32 beforeSize = kNumOpts;\n  Bool btMode;\n  if (!RangeEnc_Alloc(&p->rc, alloc))\n    return SZ_ERROR_MEM;\n  btMode = (p->matchFinderBase.btMode != 0);\n  #ifndef _7ZIP_ST\n  p->mtMode = (p->multiThread && !p->fastMode && btMode);\n  #endif\n\n  {\n    unsigned lclp = p->lc + p->lp;\n    if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)\n    {\n      LzmaEnc_FreeLits(p, alloc);\n      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));\n      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));\n      if (p->litProbs == 0 || p->saveState.litProbs == 0)\n      {\n        LzmaEnc_FreeLits(p, alloc);\n        return SZ_ERROR_MEM;\n      }\n      p->lclp = lclp;\n    }\n  }\n\n  p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);\n\n  if (beforeSize + p->dictSize < keepWindowSize)\n    beforeSize = keepWindowSize - p->dictSize;\n\n  #ifndef _7ZIP_ST\n  if (p->mtMode)\n  {\n    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));\n    p->matchFinderObj = &p->matchFinderMt;\n    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);\n  }\n  else\n  #endif\n  {\n    if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))\n      return SZ_ERROR_MEM;\n    p->matchFinderObj = &p->matchFinderBase;\n    MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);\n  }\n  return SZ_OK;\n}\n\nvoid LzmaEnc_Init(CLzmaEnc *p)\n{\n  UInt32 i;\n  p->state = 0;\n  for (i = 0 ; i < LZMA_NUM_REPS; i++)\n    p->reps[i] = 0;\n\n  RangeEnc_Init(&p->rc);\n\n\n  for (i = 0; i < kNumStates; i++)\n  {\n    UInt32 j;\n    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)\n    {\n      p->isMatch[i][j] = kProbInitValue;\n      p->isRep0Long[i][j] = kProbInitValue;\n    }\n    p->isRep[i] = kProbInitValue;\n    p->isRepG0[i] = kProbInitValue;\n    p->isRepG1[i] = kProbInitValue;\n    p->isRepG2[i] = kProbInitValue;\n  }\n\n  {\n    UInt32 num = 0x300 << (p->lp + p->lc);\n    for (i = 0; i < num; i++)\n      p->litProbs[i] = kProbInitValue;\n  }\n\n  {\n    for (i = 0; i < kNumLenToPosStates; i++)\n    {\n      CLzmaProb *probs = p->posSlotEncoder[i];\n      UInt32 j;\n      for (j = 0; j < (1 << kNumPosSlotBits); j++)\n        probs[j] = kProbInitValue;\n    }\n  }\n  {\n    for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)\n      p->posEncoders[i] = kProbInitValue;\n  }\n\n  LenEnc_Init(&p->lenEnc.p);\n  LenEnc_Init(&p->repLenEnc.p);\n\n  for (i = 0; i < (1 << kNumAlignBits); i++)\n    p->posAlignEncoder[i] = kProbInitValue;\n\n  p->optimumEndIndex = 0;\n  p->optimumCurrentIndex = 0;\n  p->additionalOffset = 0;\n\n  p->pbMask = (1 << p->pb) - 1;\n  p->lpMask = (1 << p->lp) - 1;\n}\n\nvoid LzmaEnc_InitPrices(CLzmaEnc *p)\n{\n  if (!p->fastMode)\n  {\n    FillDistancesPrices(p);\n    FillAlignPrices(p);\n  }\n\n  p->lenEnc.tableSize =\n  p->repLenEnc.tableSize =\n      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;\n  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);\n  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);\n}\n\nstatic SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  UInt32 i;\n  for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)\n    if (p->dictSize <= ((UInt32)1 << i))\n      break;\n  p->distTableSize = i * 2;\n\n  p->finished = False;\n  p->result = SZ_OK;\n  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));\n  LzmaEnc_Init(p);\n  LzmaEnc_InitPrices(p);\n  p->nowPos64 = 0;\n  return SZ_OK;\n}\n\nstatic SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,\n    ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  CLzmaEnc *p = (CLzmaEnc *)pp;\n  p->matchFinderBase.stream = inStream;\n  p->needInit = 1;\n  p->rc.outStream = outStream;\n  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);\n}\n\nSRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,\n    ISeqInStream *inStream, UInt32 keepWindowSize,\n    ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  CLzmaEnc *p = (CLzmaEnc *)pp;\n  p->matchFinderBase.stream = inStream;\n  p->needInit = 1;\n  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);\n}\n\nstatic void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)\n{\n  p->matchFinderBase.directInput = 1;\n  p->matchFinderBase.bufferBase = (Byte *)src;\n  p->matchFinderBase.directInputRem = srcLen;\n}\n\nSRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,\n    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  CLzmaEnc *p = (CLzmaEnc *)pp;\n  LzmaEnc_SetInputBuf(p, src, srcLen);\n  p->needInit = 1;\n\n  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);\n}\n\nvoid LzmaEnc_Finish(CLzmaEncHandle pp)\n{\n  #ifndef _7ZIP_ST\n  CLzmaEnc *p = (CLzmaEnc *)pp;\n  if (p->mtMode)\n    MatchFinderMt_ReleaseStream(&p->matchFinderMt);\n  #else\n  pp = pp;\n  #endif\n}\n\ntypedef struct\n{\n  ISeqOutStream funcTable;\n  Byte *data;\n  SizeT rem;\n  Bool overflow;\n} CSeqOutStreamBuf;\n\nstatic size_t MyWrite(void *pp, const void *data, size_t size)\n{\n  CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;\n  if (p->rem < size)\n  {\n    size = p->rem;\n    p->overflow = True;\n  }\n  memcpy(p->data, data, size);\n  p->rem -= size;\n  p->data += size;\n  return size;\n}\n\n\nUInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)\n{\n  const CLzmaEnc *p = (CLzmaEnc *)pp;\n  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);\n}\n\nconst Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)\n{\n  const CLzmaEnc *p = (CLzmaEnc *)pp;\n  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;\n}\n\nSRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,\n    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)\n{\n  CLzmaEnc *p = (CLzmaEnc *)pp;\n  UInt64 nowPos64;\n  SRes res;\n  CSeqOutStreamBuf outStream;\n\n  outStream.funcTable.Write = MyWrite;\n  outStream.data = dest;\n  outStream.rem = *destLen;\n  outStream.overflow = False;\n\n  p->writeEndMark = False;\n  p->finished = False;\n  p->result = SZ_OK;\n\n  if (reInit)\n    LzmaEnc_Init(p);\n  LzmaEnc_InitPrices(p);\n  nowPos64 = p->nowPos64;\n  RangeEnc_Init(&p->rc);\n  p->rc.outStream = &outStream.funcTable;\n\n  res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);\n\n  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);\n  *destLen -= outStream.rem;\n  if (outStream.overflow)\n    return SZ_ERROR_OUTPUT_EOF;\n\n  return res;\n}\n\nstatic SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)\n{\n  SRes res = SZ_OK;\n\n  #ifndef _7ZIP_ST\n  Byte allocaDummy[0x300];\n  int i = 0;\n  for (i = 0; i < 16; i++)\n    allocaDummy[i] = (Byte)i;\n  #endif\n\n  for (;;)\n  {\n    res = LzmaEnc_CodeOneBlock(p, False, 0, 0);\n    if (res != SZ_OK || p->finished != 0)\n      break;\n    if (progress != 0)\n    {\n      res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));\n      if (res != SZ_OK)\n      {\n        res = SZ_ERROR_PROGRESS;\n        break;\n      }\n    }\n  }\n  LzmaEnc_Finish(p);\n  return res;\n}\n\nSRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,\n    ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));\n  return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);\n}\n\nSRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)\n{\n  CLzmaEnc *p = (CLzmaEnc *)pp;\n  int i;\n  UInt32 dictSize = p->dictSize;\n  if (*size < LZMA_PROPS_SIZE)\n    return SZ_ERROR_PARAM;\n  *size = LZMA_PROPS_SIZE;\n  props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);\n\n  for (i = 11; i <= 30; i++)\n  {\n    if (dictSize <= ((UInt32)2 << i))\n    {\n      dictSize = (2 << i);\n      break;\n    }\n    if (dictSize <= ((UInt32)3 << i))\n    {\n      dictSize = (3 << i);\n      break;\n    }\n  }\n\n  for (i = 0; i < 4; i++)\n    props[1 + i] = (Byte)(dictSize >> (8 * i));\n  return SZ_OK;\n}\n\nSRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\n    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  SRes res;\n  CLzmaEnc *p = (CLzmaEnc *)pp;\n\n  CSeqOutStreamBuf outStream;\n\n  LzmaEnc_SetInputBuf(p, src, srcLen);\n\n  outStream.funcTable.Write = MyWrite;\n  outStream.data = dest;\n  outStream.rem = *destLen;\n  outStream.overflow = False;\n\n  p->writeEndMark = writeEndMark;\n\n  p->rc.outStream = &outStream.funcTable;\n  res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);\n  if (res == SZ_OK)\n    res = LzmaEnc_Encode2(p, progress);\n\n  *destLen -= outStream.rem;\n  if (outStream.overflow)\n    return SZ_ERROR_OUTPUT_EOF;\n  return res;\n}\n\nSRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\n    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,\n    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)\n{\n  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);\n  SRes res;\n  if (p == 0)\n    return SZ_ERROR_MEM;\n\n  res = LzmaEnc_SetProps(p, props);\n  if (res == SZ_OK)\n  {\n    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);\n    if (res == SZ_OK)\n      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,\n          writeEndMark, progress, alloc, allocBig);\n  }\n\n  LzmaEnc_Destroy(p, alloc, allocBig);\n  return res;\n}\n"
  },
  {
    "path": "src/lzo-lg.c",
    "content": "/* lzopack.c -- LZO example program: a simple file packer\n\n This file is part of the LZO real-time data compression library.\n\n Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer\n All Rights Reserved.\n\n Patched by Arno1 (http://lg-hack.info) for LG digital tv firmware\n\n The LZO library is free software; you can redistribute it and/or\n modify it under the terms of the GNU General Public License as\n published by the Free Software Foundation; either version 2 of\n the License, or (at your option) any later version.\n\n The LZO library 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 You should have received a copy of the GNU General Public License\n along with the LZO library; see the file COPYING.\n If not, write to the Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\n Markus F.X.J. Oberhumer\n <markus@oberhumer.com>\n http://www.oberhumer.com/opensource/lzo/\n */\n\n/*************************************************************************\n // NOTE: this is an example program, so do not use to backup your data.\n //\n // This program lacks things like sophisticated file handling but is\n // pretty complete regarding compression - it should provide a good\n // starting point for adaption for your applications.\n //\n // Please study LZO.FAQ and simple.c first.\n **************************************************************************/\n#include \"common.h\"\n\n#include \"lzo/lzoconf.h\"\n#include \"lzo/lzo1x.h\"\n\n/* portability layer */\n#define WANT_LZO_MALLOC 1\n#define WANT_LZO_FREAD 1\n#define WANT_LZO_WILDARGV 1\n#include \"lzo/portab.h\"\n\nstatic unsigned long total_in = 0;\nstatic unsigned long total_out = 0;\nstatic lzo_bool opt_debug = 0;\n\nlzo_uint32 fi_size = 0;\n\n/* magic file header for lzopack-compressed files */\nstatic const unsigned char magic[8] = { 0x00, 0xe9, 0x4c, 0x5a, 0x4f, 0xff,\n\t0x1a, 0x00\n};\n\n/*************************************************************************\n // file IO\n **************************************************************************/\n\nlzo_uint xread(FILE * fp, lzo_voidp buf, lzo_uint len, lzo_bool allow_eof) {\n\tlzo_uint l;\n\n\tl = (lzo_uint) lzo_fread(fp, buf, len);\n\tif (l > len) {\n\t\tfprintf(stderr, \"\\nsomething's wrong with your C library !!!\\n\");\n\t\texit(1);\n\t}\n\tif (l != len && !allow_eof) {\n\t\tfprintf(stderr, \"\\nread error - premature end of file\\n\");\n\t\texit(1);\n\t}\n\ttotal_in += (unsigned long)l;\n\treturn l;\n}\n\nlzo_uint xwrite(FILE * fp, const lzo_voidp buf, lzo_uint len) {\n\tif (fp != NULL && lzo_fwrite(fp, buf, len) != len) {\n\t\tfprintf(stderr, \"\\nwrite error  (disk full ?)\\n\");\n\t\texit(1);\n\t}\n\ttotal_out += (unsigned long)len;\n\treturn len;\n}\n\nint xgetc(FILE * fp) {\n\tunsigned char c;\n\txread(fp, (lzo_voidp) & c, 1, 0);\n\treturn c;\n}\n\nvoid xputc(FILE * fp, int c) {\n\tunsigned char cc = (unsigned char)(c & 0xff);\n\txwrite(fp, (const lzo_voidp)&cc, 1);\n}\n\n/* read and write portable 32-bit integers */\n\nlzo_uint32 xread32(FILE * fp) {\n\tunsigned char b[4];\n\tlzo_uint32 v;\n\n\txread(fp, b, 4, 0);\n\tv = (lzo_uint32) b[3] << 0;\n\tv |= (lzo_uint32) b[2] << 8;\n\tv |= (lzo_uint32) b[1] << 16;\n\tv |= (lzo_uint32) b[0] << 24;\n\treturn v;\n}\n\nvoid xwrite32(FILE * fp, lzo_xint v) {\n\tunsigned char b[4];\n\n\tb[3] = (unsigned char)((v >> 0) & 0xff);\n\tb[2] = (unsigned char)((v >> 8) & 0xff);\n\tb[1] = (unsigned char)((v >> 16) & 0xff);\n\tb[0] = (unsigned char)((v >> 24) & 0xff);\n\txwrite(fp, b, 4);\n}\n\n/*************************************************************************\n // compress\n //\n // possible improvement: we could use overlapping compression to\n //   save some memory - see overlap.c. This would require some minor\n //   changes in the decompression code as well, because if a block\n //   turns out to be incompressible we would still have to store it in its\n //   \"compressed\" (i.e. then slightly enlarged) form because the original\n //   (uncompressed) data would have been lost during the overlapping\n //   compression.\n **************************************************************************/\n\nint do_compress(FILE * fi, FILE * fo, int level, lzo_uint block_size) {\n\tint r = 0;\n\tlzo_bytep in = NULL;\n\tlzo_bytep out = NULL;\n\tlzo_bytep wrkmem = NULL;\n\tlzo_uint in_len;\n\tlzo_uint out_len;\n\tlzo_uint32 wrk_len = 0;\n\tlzo_uint32 flags = 1;\t\t/* do compute a checksum */\n\tint method = 1;\t\t\t\t/* compression method: LZO1X */\n\tlzo_uint32 checksum;\n\n\ttotal_in = total_out = 0;\n\n\t/*\n\t * Step 1: write magic header, flags & block size, init checksum\n\t */\n\txwrite(fo, magic, sizeof(magic));\n\txwrite32(fo, fi_size);\n\tprintf(\"Decompressed size : %d\\n\", fi_size);\n\txwrite32(fo, flags);\n\txputc(fo, method);\t\t\t/* compression method */\n\txputc(fo, level);\t\t\t/* compression level */\n\txwrite32(fo, block_size);\n\tchecksum = lzo_adler32(0, NULL, 0);\n\n\t/*\n\t * Step 2: allocate compression buffers and work-memory\n\t */\n\tin = (lzo_bytep) lzo_malloc(block_size);\n\tout = (lzo_bytep) lzo_malloc(block_size + block_size / 16 + 64 + 3);\n\tif (level == 9)\n\t\twrk_len = LZO1X_999_MEM_COMPRESS;\n\telse\n\t\twrk_len = LZO1X_1_MEM_COMPRESS;\n\twrkmem = (lzo_bytep) lzo_malloc(wrk_len);\n\tif (in == NULL || out == NULL || wrkmem == NULL) {\n\t\tprintf(\"out of memory\\n\");\n\t\tr = 1;\n\t\tgoto err;\n\t}\n\n\t/*\n\t * Step 3: process blocks\n\t */\n\tfor (;;) {\n\t\t/* read block */\n\t\tin_len = xread(fi, in, block_size, 1);\n\t\tif (in_len <= 0)\n\t\t\tbreak;\n\n\t\t/* update checksum */\n\t\tif (flags & 1)\n\t\t\tchecksum = lzo_adler32(checksum, in, in_len);\n\n\t\t/* clear wrkmem (not needed, only for debug/benchmark purposes) */\n\t\tif (opt_debug)\n\t\t\tlzo_memset(wrkmem, 0xff, wrk_len);\n\n\t\t/* compress block */\n\t\tif (level == 9)\n\t\t\tr = lzo1x_999_compress(in, in_len, out, &out_len, wrkmem);\n\t\telse\n\t\t\tr = lzo1x_1_compress(in, in_len, out, &out_len, wrkmem);\n\t\tif (r != LZO_E_OK || out_len > in_len + in_len / 16 + 64 + 3) {\n\t\t\t/* this should NEVER happen */\n\t\t\tprintf(\"internal error - compression failed: %d\\n\", r);\n\t\t\tr = 2;\n\t\t\tgoto err;\n\t\t}\n\n\t\t/* write uncompressed block size */\n\t\txwrite32(fo, in_len);\n\n\t\tif (out_len < in_len) {\n\t\t\t/* write compressed block */\n\t\t\txwrite32(fo, out_len);\n\t\t\txwrite(fo, out, out_len);\n\t\t} else {\n\t\t\t/* not compressible - write uncompressed block */\n\t\t\txwrite32(fo, in_len);\n\t\t\txwrite(fo, in, in_len);\n\t\t}\n\t}\n\n\t/* write EOF marker */\n\txwrite32(fo, 0);\n\n\t/* write checksum */\n\tif (flags & 1)\n\t\txwrite32(fo, checksum);\n\n\tr = 0;\n err:lzo_free(wrkmem);\n\tlzo_free(out);\n\tlzo_free(in);\n\treturn r;\n}\n\n/*************************************************************************\n // decompress / test\n //\n // We are using overlapping (in-place) decompression to save some\n // memory - see overlap.c.\n **************************************************************************/\n\nint do_decompress(FILE * fi, FILE * fo) {\n\tunsigned int r = 0;\n\tlzo_bytep buf = NULL;\n\tlzo_uint buf_len;\n\tunsigned char m[sizeof(magic)];\n\tlzo_uint32 flags, UNUSED(decomp_size);\n\tint method;\n\tint level;\n\tlzo_uint block_size;\n\tlzo_uint32 checksum;\n\n\ttotal_in = total_out = 0;\n\n\t/*\n\t * Step 1: check magic header, read flags & block size, init checksum\n\t */\n\tif (xread(fi, m, sizeof(magic), 1) != sizeof(magic) || memcmp(m, magic, sizeof(magic)) != 0) {\n\t\t//printf(\"header error - this file is not compressed by lzopack\\n\");\n\t\tr = 1;\n\t\tgoto err;\n\t}\n\n\t//decomp_size = xread32(fi);\n\n\tflags = xread32(fi);\n\n\tmethod = xgetc(fi);\n\n\tif (method != 1) {\n\t\t// check for different LZO header including version\n\t\t// TODO: convert this to structs with MFILE\n\t\tfseek(fi, -1, SEEK_CUR);\n\n\t\tuint32_t version = xread32(fi);\n\t\tif(version != 1){\n\t\t\theader_error:\n\t\t\t\tprintf(\"header error - invalid method %d (version: %d)\\n\", method, version);\n\t\t\t\tr = 2;\n\t\t\t\tgoto err;\n\t\t}\n\n\t\tmethod = xgetc(fi);\n\t\tif(method != 1){\n\t\t\tgoto header_error;\n\t\t}\n\t}\n\n\tlevel = xgetc(fi);\n\n\tblock_size = xread32(fi);\n\tif (block_size < 1024 || block_size > 8 * 1024 * 1024L) {\n\t\tprintf(\"header error - invalid block size %ld\\n\", (long)block_size);\n\t\tr = 3;\n\t\tgoto err;\n\t}\n\tchecksum = lzo_adler32(0, NULL, 0);\n\n\t/*\n\t * Step 2: allocate buffer for in-place decompression\n\t */\n\tbuf_len = block_size + block_size / 16 + 64 + 3;\n\tbuf = (lzo_bytep) lzo_malloc(buf_len);\n\tif (buf == NULL) {\n\t\tprintf(\"out of memory\\n\");\n\t\tr = 4;\n\t\tgoto err;\n\t}\n\n\t/*\n\t * Step 3: process blocks\n\t */\n\tfor (;;) {\n\t\tlzo_bytep in;\n\t\tlzo_bytep out;\n\t\tlzo_uint in_len;\n\t\tlzo_uint out_len;\n\n\t\t/* read uncompressed size */\n\t\tout_len = xread32(fi);\n\n\t\t/* exit if last block (EOF marker) */\n\t\tif (out_len == 0)\n\t\t\tbreak;\n\n\t\t/* read compressed size */\n\t\tin_len = xread32(fi);\n\n\t\t/* sanity check of the size values */\n\t\tif (in_len > block_size || out_len > block_size || in_len == 0 || in_len > out_len) {\n\t\t\tprintf(\"block size error - data corrupted\\n\");\n\t\t\tr = 5;\n\t\t\tgoto err;\n\t\t}\n\n\t\t/* place compressed block at the top of the buffer */\n\t\tin = buf + buf_len - in_len;\n\t\tout = buf;\n\n\t\t/* read compressed block data */\n\t\txread(fi, in, in_len, 0);\n\n\t\tif (in_len < out_len) {\n\t\t\t/* decompress - use safe decompressor as data might be corrupted\n\t\t\t * during a file transfer */\n\t\t\tlzo_uint new_len = out_len;\n\n\t\t\tr = lzo1x_decompress_safe(in, in_len, out, &new_len, NULL);\n\t\t\tif (r != LZO_E_OK || new_len != out_len) {\n\t\t\t\tprintf(\"compressed data violation: %u\\n\", r);\n\t\t\t\tr = 6;\n\t\t\t\tgoto err;\n\t\t\t}\n\t\t\t/* write decompressed block */\n\t\t\txwrite(fo, out, out_len);\n\t\t\t/* update checksum */\n\t\t\tif (flags & 1)\n\t\t\t\tchecksum = lzo_adler32(checksum, out, out_len);\n\t\t} else {\n\t\t\t/* write original (incompressible) block */\n\t\t\txwrite(fo, in, in_len);\n\t\t\t/* update checksum */\n\t\t\tif (flags & 1)\n\t\t\t\tchecksum = lzo_adler32(checksum, in, in_len);\n\t\t}\n\t}\n\n\t/* read and verify checksum */\n\tif (flags & 1) {\n\t\tlzo_uint32 c = xread32(fi);\n\t\tif (c != checksum) {\n\t\t\tprintf(\"checksum error - data corrupted\\n\");\n\t\t\tr = 7;\n\t\t\tgoto err;\n\t\t}\n\t}\n\n\tr = 0;\n err:lzo_free(buf);\n\treturn r;\n}\n\n/*************************************************************************\n //\n **************************************************************************/\n\n/* open input file */\nstatic FILE *xopen_fi(const char *name) {\n\tFILE *fp;\n\n\tfp = fopen(name, \"rb\");\n\tif (fp == NULL) {\n\t\tprintf(\"cannot open input file %s\\n\", name);\n\t\texit(1);\n\t} else {\n\t\tstruct stat st;\n\t\tint is_regular = 1;\n\t\tif (stat(name, &st) != 0 || !S_ISREG(st.st_mode))\n\t\t\tis_regular = 0;\n\t\telse\n\t\t\tfi_size = (lzo_uint32) st.st_size;\n\t\tif (!is_regular) {\n\t\t\tprintf(\"%s is not a regular file\\n\", name);\n\t\t\tfclose(fp);\n\t\t\tfp = NULL;\n\t\t\texit(1);\n\t\t}\n\t}\n\n\treturn fp;\n}\n\n/* open output file */\nstatic FILE *xopen_fo(const char *name) {\n\tFILE *fp;\n\n#if 0\n\t/* this is an example program, so make sure we don't overwrite a file */\n\tfp = fopen(name, \"rb\");\n\tif (fp != NULL) {\n\t\tprintf(\"%s: file %s already exists -- not overwritten\\n\", progname, name);\n\t\tfclose(fp);\n\t\tfp = NULL;\n\t\texit(1);\n\t}\n#endif\n\tfp = fopen(name, \"wb\");\n\tif (fp == NULL) {\n\t\tprintf(\"cannot open output file %s\\n\", name);\n\t\texit(1);\n\t}\n\treturn fp;\n}\n\n/* close file */\nstatic void xclose(FILE * fp) {\n\tif (fp) {\n\t\tint err;\n\t\terr = ferror(fp);\n\t\tif (fclose(fp) != 0)\n\t\t\terr = 1;\n\t\tif (err) {\n\t\t\tprintf(\"error while closing file\\n\");\n\t\t\texit(1);\n\t\t}\n\t}\n}\n\nint check_lzo_header(const char *name) {\n\n\tFILE *fi = xopen_fi(name);\n\n\tunsigned char m[sizeof(magic)];\n\tint result = (xread(fi, m, sizeof(magic), 1) != sizeof(magic) || memcmp(m, magic,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsizeof(magic)) != 0);\n\n\txclose(fi);\n\n\treturn !result;\n}\n\n/*************************************************************************\n //\n **************************************************************************/\n\nint __lzo_cdecl_main lzo_unpack(const char *in_name, const char *out_name) {\n\n\tint r = 0;\n\tFILE *fi = NULL;\n\tFILE *fo = NULL;\n\tlzo_uint UNUSED(opt_block_size);\n\n\t/*\n\t * Step 1: initialize the LZO library\n\t */\n\tif (lzo_init() != LZO_E_OK) {\n\t\tprintf(\"internal error - lzo_init() failed !!!\\n\");\n\t\tprintf(\"(this usually indicates a compiler bug - try recompiling\\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\\n\");\n\t\texit(1);\n\t}\n\n#if 0\n\t/*\n\t * Step 2: setup memory\n\t */\n\topt_block_size = 256 * 1024L;\n\n#if defined(ACC_MM_AHSHIFT)\n\t/* reduce memory requirements for ancient 16-bit DOS 640kB real-mode */\n\tif (ACC_MM_AHSHIFT != 3)\n\t\topt_block_size = 16 * 1024L;\n#endif\n#endif\n\n\t/*\n\t * Step 4: process file(s)\n\t */\n\tfi = xopen_fi(in_name);\n\tfo = xopen_fo(out_name);\n\tr = do_decompress(fi, fo);\n//  if (r == 0) printf(\"decompressed %lu into %lu bytes\\n\", total_in, total_out);\n\txclose(fi);\n\tfi = NULL;\n\txclose(fo);\n\tfo = NULL;\n\treturn r;\n}\n\n/*\n vi:ts=4:et\n */\n"
  },
  {
    "path": "src/main.c",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * Copyright 20?? sirius\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <ctype.h>\n#include <string.h>\n#include <unistd.h>\n#include <libgen.h>\n#include <getopt.h>\n#ifdef __CYGWIN__\n#    include <sys/cygwin.h>\n#endif\n\n#include \"config.h\"\n#include \"mfile.h\"\n#include \"epk.h\"\n#include \"epk1.h\"\t\t/* EPK v1 */\n#include \"epk2.h\"\t\t/* EPK v2 */\n#include \"epk3.h\"\t\t/* EPK v3 */\n#include \"cramfs/cramfs.h\"\t/* CRAMFS */\n#include \"cramfs/cramfsswap.h\"\n#include \"lz4/lz4.h\"\t/* LZ4 */\n#include \"lzo/lzo.h\"\t/* LZO */\n#include \"lzhs/lzhs.h\"\t/* LZHS */\n#include \"jffs2/jffs2.h\"\t/* JFFS2 */\n#include \"squashfs/unsquashfs.h\"\t/* SQUASHFS */\n#include \"minigzip.h\"\t/* GZIP */\n#include \"symfile.h\"\t/* SYM */\n#include \"stream/tsfile.h\"\t\t/* STR and PIF */\n#include \"mediatek.h\"\t/* MTK Boot */\n#include \"mediatek_pkg.h\"\t/* MTK UPG */\n#include \"realtek.h\"\n#include \"philips.h\"\n#include \"u-boot/partinfo.h\"\t/* PARTINFO */\n#include \"util.h\"\n\n#ifdef __APPLE__\n#include <mach-o/dyld.h>\n#endif\n\nstatic int print_usage(void);\n\nconfig_opts_t config_opts;\n\nint handle_file(char *file, config_opts_t *config_opts) {\n\tchar *dest_dir = config_opts->dest_dir;\n\tchar *file_name = my_basename(file);\n\n\tchar *file_base = remove_ext(file_name);\n\t//const char *file_ext = get_ext(strdup(file_name));\n\tchar *dest_file = NULL;\n\n\tint result = EXIT_SUCCESS;\n\n\tMFILE *mf = NULL;\n\tif (isFileEPK1(file)) {\n\t\tif (config_opts->signatureOnly) {\n\t\t\tprintf(\"EPK1 is not signed; nothing to do\\n\");\n\t\t} else {\n\t\t\textract_epk1_file(file, config_opts);\n\t\t}\n\t} else if (isFileEPK2(file) || isFileEPK3(file)) {\n\t\textractEPKfile(file, config_opts);\n\t} else if (config_opts->signatureOnly) {\n\t\t/* none of the following file types have signatures */\n\t\tprintf(\"Only EPKs supported in signature-only mode\\n\");\n\t\tresult = EXIT_FAILURE;\n\t} else if((mf=is_mtk_pkg(file))){\n\t\textract_mtk_pkg(file, config_opts);\n\t} else if((mf=is_firm_image(file))){\n\t\textract_firm_image(mf);\n\t} else if((mf=is_philips_fusion1(file))){\n\t\textract_philips_fusion1(mf, config_opts);\n\t} else if((mf=is_lzhs_fs(file))){\n\t\tasprintf(&dest_file, \"%s/%s.ext4\", dest_dir, file_name);\n\t\textract_lzhs_fs(mf, dest_file, config_opts);\n\t/* LZ4 */\n\t} else if ((mf=is_lz4(file))) {\n\t\tasprintf(&dest_file, \"%s/%s.unlz4\", dest_dir, file_name);\n\t\tprintf(\"UnLZ4 file to: %s\\n\", dest_file);\n\t\tif (!LZ4_decode_file(file, dest_file))\n\t\t\thandle_file(dest_file, config_opts);\n\t/* LZO */\n\t} else if (check_lzo_header(file)) {\n\t\tif (!strcmp(file_name, \"logo.pak\"))\n\t\t\tasprintf(&dest_file, \"%s/%s.bmp\", dest_dir, file_name);\n\t\telse\n\t\t\tasprintf(&dest_file, \"%s/%s.unlzo\", dest_dir, file_name);\n\t\tprintf(\"UnLZO file to: %s\\n\", dest_file);\n\t\tif (!lzo_unpack(file, dest_file))\n\t\t\thandle_file(dest_file, config_opts);\n\t/* NFSB */\n\t} else if ((mf=is_nfsb(file))) {\n\t\tasprintf(&dest_file, \"%s/%s.unnfsb\", dest_dir, file_name);\n\t\tprintf(\"UnNFSB file to: %s\\n\", dest_file);\n\t\tunnfsb(file, dest_file);\n\t\thandle_file(dest_file, config_opts);\n\t/* SQUASHFS */\n\t} else if (is_squashfs(file)) {\n\t\tif (!config_opts->noAutoUnsquashfs) {\n\t\t\tasprintf(&dest_file, \"%s/%s.unsquashfs\", dest_dir, file_name);\n\t\t\tprintf(\"UnSQUASHFS file to: %s\\n\", dest_file);\n\t\t\trmrf(dest_file);\n\t\t\tunsquashfs(file, dest_file);\n\t\t} else {\n\t\t\tputs(\"Not UnSQUASHFSing\");\n\t\t}\n\t/* GZIP */\n\t} else if ((mf=is_gzip(file))) {\n\t\tasprintf(&dest_file, \"%s/\", dest_dir);\n\t\tprintf(\"UnGZIP %s to folder %s\\n\", file, dest_file);\n\t\tchar *gz_name = file_uncompress_origname(file, dest_file);\n\t\thandle_file(gz_name, config_opts);\n\t\tfree(gz_name);\n\t/* MTK boot partition */\n\t} else if ((mf=is_mtk_boot(file))) {\n\t\tasprintf(&dest_file, \"%s/mtk_1bl.bin\", dest_dir);\n\n\t\tprintf(\"[MTK] Extracting 1BL to mtk_1bl.bin...\\n\");\n\t\textract_mtk_1bl(mf, dest_file);\n\n\t\tprintf(\"[MTK] Extracting embedded LZHS files...\\n\");\n\t\textract_lzhs(mf);\n\t/* Realtek BSPFW partition */\n\t} else if ((mf=is_rtk_bspfw(file))) {\n\t\tprintf(\"[RTK] Splitting bspfw.pak...\\n\");\n\t\tsplit_rtk_bspfw(mf, dest_dir);\n\t/* CRAMFS Big Endian */\n\t} else if (is_cramfs_image(file, \"be\")) {\n\t\tasprintf(&dest_file, \"%s/%s.cramswap\", dest_dir, file_name);\n\t\tprintf(\"Swapping cramfs endian for file %s\\n\", file);\n\t\tcramswap(file, dest_file);\n\t\thandle_file(dest_file, config_opts);\n\t/* CRAMFS Little Endian */\n\t} else if (is_cramfs_image(file, \"le\")) {\n\t\tasprintf(&dest_file, \"%s/%s.uncramfs\", dest_dir, file_name);\n\t\tprintf(\"UnCRAMFS %s to folder %s\\n\", file, dest_file);\n\t\trmrf(dest_file);\n\t\tuncramfs(dest_file, file);\n\t/* Kernel uImage */\n\t} else if (is_kernel(file)) {\n\t\tasprintf(&dest_file, \"%s/%s.unpaked\", dest_dir, file_name);\n\t\tprintf(\"Extracting boot image (kernel) to: %s\\n\", dest_file);\n\t\textract_kernel(file, dest_file);\n\t\thandle_file(dest_file, config_opts);\n\t/* Partition Table (partinfo) */\n\t} else if (isPartPakfile(file)) {\n\t\tasprintf(&dest_file, \"%s/%s.txt\", dest_dir, file_base);\n\t\tprintf(\"Saving partition info to: %s\\n\", dest_file);\n\t\tdump_partinfo(file, dest_file);\n\t/* JFFS2 */\n\t} else if (is_jffs2(file)) {\n\t\tasprintf(&dest_file, \"%s/%s.unjffs2\", dest_dir, file_name);\n\t\tprintf(\"UnJFFS2 file %s to folder %s\\n\", file, dest_file);\n\t\trmrf(dest_file);\n\n\t\tstruct jffs2_main_args args = {\n\t\t\t.erase_size = -1,\n\t\t\t.keep_unlinked = false,\n\t\t\t.verbose = 0\n\t\t};\n\n\t\tjffs2extract(file, dest_file, args);\n\t/* PVR STR (ts/m2ts video) */\n\t} else if (isSTRfile(file)) {\n\t\tasprintf(&dest_file, \"%s/%s.ts\", dest_dir, file_name);\n\t\tprintf(\"\\nConverting %s file to TS\\n\", file);\n\n\t\tstruct tsfile_options opts = {\n\t\t\t.video_stream_type = -1,\n\t\t\t.audio_stream_type = -1,\n\t\t\t.append = 0\n\t\t};\n\t\tconvertSTR2TS(file, &opts);\n\t/* PVR PIF (Program Information File) */\n\t} else if (!strncasecmp(&file[strlen(file) - 3], \"PIF\", 3)) {\n\t\tasprintf(&dest_file, \"%s/%s.ts\", dest_dir, file_name);\n\t\tprintf(\"\\nProcessing PIF file: %s\\n\", file);\n\t\tprocessPIF(file, dest_file);\n\t/* SYM File (Debugging information) */\n\t} else if (symfile_load(file) == 0) {\n\t\tasprintf(&dest_file, \"%s/%s.idc\", dest_dir, file_name);\n\t\tprintf(\"Converting SYM file to IDC script: %s\\n\", dest_file);\n\t\tsymfile_write_idc(dest_file);\n\t/* MTK LZHS (Modified LZSS + Huffman) */\n\t} else if ((mf=is_lzhs(file))) {\n\t\tasprintf(&dest_file, \"%s/%s.unlzhs\", dest_dir, file_name);\n\t\tprintf(\"UnLZHS %s to %s\\n\", file, dest_file);\n\t\tlzhs_decode(mf, 0, dest_file, NULL);\n\t/* MTK TZFW (TrustZone Firmware) */\n\t} else if (!strcmp(file_name, \"tzfw.pak\") && (mf=is_elf(file))) {\n\t\tprintf(\"Splitting mtk tzfw...\\n\");\n\t\tsplit_mtk_tz(mf, dest_dir);\n\t} else {\n\t\tresult = EXIT_FAILURE;\n\t}\n\n\tif(mf != NULL)\n\t\tmclose(mf);\n\n\tfree(file_name);\n\tfree(file_base);\n\n\tif(dest_file != NULL)\n\t\tfree(dest_file);\n\n\treturn result;\n}\n\nint main(int argc, char *argv[]) {\n\tprintf(\"\\nLG Electronics digital TV firmware package (EPK) extractor version 4.8 (http://openlgtv.org.ru)\\n\\n\");\n\tif (argc < 2) {\n\t\treturn print_usage();\n\t}\n\n\tchar *exe_dir = calloc(1, PATH_MAX);\n\tchar *current_dir = calloc(1, PATH_MAX);\n\n\t#ifdef __APPLE__\n\tuint32_t pathsz = PATH_MAX;\n\tif (_NSGetExecutablePath(exe_dir, &pathsz) == 0){\n\t\tprintf(\"Executable path is %s\\n\", exe_dir);\n\t} else {\n\t\tprintf(\"Buffer too small; need size %u\\n\", PATH_MAX);\n\t\treturn EXIT_FAILURE;\n\t}\n\tconfig_opts.config_dir = my_dirname(exe_dir);\n\t#else\n\tgetcwd(current_dir, PATH_MAX);\n\tprintf(\"Current directory: %s\\n\", current_dir);\n\treadlink(\"/proc/self/exe\", exe_dir, PATH_MAX);\n\t#endif\n\n\tconfig_opts.config_dir = my_dirname(exe_dir);\n\tconfig_opts.dest_dir = calloc(1, PATH_MAX);\n\tconfig_opts.enableSignatureChecking = 0;\n\tconfig_opts.noAutoUnsquashfs = false;\n\tconfig_opts.signatureOnly = false;\n\n\tint opt;\n\twhile ((opt = getopt(argc, argv, \"csnS\")) != -1) {\n\t\tswitch (opt) {\n\t\tcase 's':{\n\t\t\tconfig_opts.enableSignatureChecking = 1;\n\t\t\tbreak;\n\t\t}\n\t\tcase 'c':{\n\t\t\t\tstrcpy(config_opts.dest_dir, current_dir);\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase 'n':{\n\t\t\t\tconfig_opts.noAutoUnsquashfs = true;\n\t\t\t\tbreak;\n\t\t\t }\n\t\tcase 'S':{\n\t\t\t\tconfig_opts.signatureOnly = true;\n\t\t\t\tconfig_opts.enableSignatureChecking = 1;\n\t\t\t\tbreak;\n\t\t\t }\n\t\tcase ':':{\n\t\t\t\tprintf(\"Option `%c' needs a value\\n\\n\", optopt);\n\t\t\t\texit(1);\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase '?':{\n\t\t\t\tprintf(\"Unknown option: `%c'\\n\\n\", optopt);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (optind == argc) {\n\t\t/* no non-option args */\n\t\treturn print_usage();\n\t}\n\n#ifdef __CYGWIN__\n\tchar posix[PATH_MAX];\n\tcygwin_conv_path(CCP_WIN_A_TO_POSIX, argv[optind], posix, PATH_MAX);\n\tchar *input_file = posix;\n#else\n\tchar *input_file = argv[optind];\n#endif\n\tprintf(\"Input file: %s\\n\", input_file);\n\tchar *dname = NULL;\n\tif (strlen(config_opts.dest_dir) == 0){\n\t\t\tdname = my_dirname(input_file);\n\t\t\tstrcpy(config_opts.dest_dir, dname);\n\t}\n\tif (strlen(config_opts.dest_dir) == 0 && config_opts.dest_dir[0] == '.'){\n\t\tdname = my_dirname(exe_dir);\n\t\tstrcpy(config_opts.dest_dir, dname);\n\t}\n\tfree(dname);\n\n\tprintf(\"Destination directory: %s\\n\", config_opts.dest_dir);\n\n\tfree(exe_dir);\n\tfree(current_dir);\n\n\tint exit_code = handle_file(input_file, &config_opts);\n\n\tif (exit_code == EXIT_FAILURE) {\n\t\treturn err_ret(\"Unsupported input file format: %s\\n\\n\", input_file);\n\t}\n\n\t(void) err_ret(\"\\nExtraction is finished.\\n\\n\");\n\treturn EXIT_SUCCESS;\n}\n\nstatic int print_usage(void) {\n\tprintf(\"Usage: epk2extract [-options] FILENAME\\n\\n\");\n\tprintf(\"Options:\\n\");\n\tprintf(\"  -c : extract to current directory instead of source file directory\\n\");\n\tprintf(\"  -s : enable signature checking for EPK files\\n\");\n\tprintf(\"  -S : only check signature (implies -s)\\n\");\n\tprintf(\"  -n : no automatic unsquashfs\\n\\n\");\n\treturn err_ret(NULL);\n}\n"
  },
  {
    "path": "src/mediatek.c",
    "content": "/**\n * Mediatek bootloader handling\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <errno.h>\n\n#include \"mfile.h\"\n#include \"mediatek.h\"\n#include \"util.h\"\n\n//lzhs\n//#include \"lzhs/lzhs.h\"\n\n//boot and tzfw\n#include <elf.h>\n\nvoid extract_mtk_1bl(MFILE *in, const char *outname) {\n\tMFILE *out = mfopen(outname, \"w+\");\n\tif (out == NULL){\n\t\terr_exit(\"Can't open file %s for writing (%s)\\n\", outname, strerror(errno));\n\t}\n\n\tsize_t pbl_size = 0;\n\n\tuint8_t *data = mdata(in, uint8_t);\n\tif(memcmp(data + 0x100, MTK_PBL_MAGIC, strlen(MTK_PBL_MAGIC)) == 0)\n\t\tpbl_size = MTK_PBL_SIZE;\n\telse if(memcmp(data + 0x100, MTK_ROM_MAGIC, strlen(MTK_ROM_MAGIC)) == 0)\n\t\tpbl_size = MTK_ROM_SIZE;\n\telse\n\t\terr_exit(\"Cannot detect PBL size\\n\");\n\n\tprintf(\"[MTK] PBL Size: 0x%08X\\n\", pbl_size);\n\n\tmfile_map(out, pbl_size);\n\tmemcpy(\n\t\tmdata(out, uint8_t),\n\t\tmdata(in, uint8_t),\n\t\tpbl_size\n\t);\n\n\tmclose(out);\n}\n\nvoid split_mtk_tz(MFILE *tz, const char *destdir) {\n\tsize_t tz_size;\n\n\tchar *dest;\n\tasprintf(&dest, \"%s/env.o\", destdir);\n\n\tMFILE *out = mfopen(dest, \"w+\");\n\tif (out == NULL)\n\t\terr_exit(\"Can't open file %s for writing\\n\", dest);\n\n\ttz_size = msize(tz) - MTK_ENV_SIZE;\n\tprintf(\"Extracting env.o... (%d bytes)\\n\", MTK_ENV_SIZE);\n\n\tuint8_t *data = mdata(tz, uint8_t);\n\n\n\tmfile_map(out, MTK_ENV_SIZE);\n\tmemcpy(mdata(out, void), data, MTK_ENV_SIZE);\n\n\tfree(dest);\n\tmclose(out);\n\n\tasprintf(&dest, \"%s/tz.bin\", destdir);\n\n\tout = mfopen(dest, \"w+\");\n\tif (out == NULL)\n\t\terr_exit(\"Can't open file %s for writing\\n\", dest);\n\n\tmfile_map(out, tz_size);\n\n\tprintf(\"Extracting tz.bin... (%zu bytes)\\n\", tz_size);\n\tmemcpy(mdata(out, void), data + MTK_ENV_SIZE, tz_size);\n\n\tfree(dest);\n\tmclose(out);\n}\n\nMFILE *is_mtk_boot(const char *filename) {\n\tMFILE *file = mopen(filename, O_RDONLY);\n\tuint8_t *data = mdata(file, uint8_t);\n\tif (file == NULL) {\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\t}\n\tif (\n\t\t(msize(file) >= MTK_PBL_SIZE) &&\n\t\t(memcmp(data + 0x100, MTK_PBL_MAGIC, strlen(MTK_PBL_MAGIC)) == 0)\n\t){\n\t\tprintf(\"Found valid PBL magic: \"MTK_PBL_MAGIC\"\\n\");\n\t} else if (\n\t\t(msize(file) >= MTK_ROM_SIZE) &&\n\t\t(memcmp(data + 0x100, MTK_ROM_MAGIC, strlen(MTK_ROM_MAGIC)) == 0)\n\t){\n\t\tprintf(\"Found valid PBL/ROM magic: \"MTK_ROM_MAGIC\"\\n\");\n\t} else {\n\t\tmclose(file);\n\t\treturn NULL;\n\t}\n\n\treturn file;\n}\n\nint is_elf_mem(Elf32_Ehdr * header) {\n\tif (!memcmp(&header->e_ident, ELFMAG, 4))\n\t\treturn 1;\n\treturn 0;\n}\n\nMFILE *is_elf(const char *filename) {\n\tMFILE *file = mopen(filename, O_RDONLY);\n\tif (file == NULL) {\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\t}\n\n\tElf32_Ehdr *elfHdr = mdata(file, Elf32_Ehdr);\n\tif (!memcmp(&(elfHdr->e_ident), ELFMAG, 4))\n\t\treturn file;\n\n\tmclose(file);\n\treturn NULL;\n}\n"
  },
  {
    "path": "src/mediatek_pkg.c",
    "content": "/**\n * Mediatek PKG Handling\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <unistd.h>\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <string.h>\n#include <pthread.h>\n#include \"main.h\" //for handle_file\n#include \"mfile.h\"\n#include \"mediatek_pkg.h\"\n#include \"lzhs/lzhs.h\"\n#include \"util.h\"\n#include \"util_crypto.h\"\n#include \"thpool.h\"\n\nenum mtkpkg_variant {\n\tOLD = 1 << 0,\n\tNEW = 1 << 1,\n\tTHOMPSON = 1 << 2,\n\tPHILIPS = 1 << 3,\n\tSHARP = 1 << 4\n};\n\n#define SIZEOF_THOMPSON_HEADER 0x170\n#define SIZEOF_OLD_HEADER 0x98\n\nstatic int mtkpkg_variant_flags = NEW;\n\nstatic struct mtkupg_header packageHeader;\nstatic bool was_decrypted = false;\n\nint compare_pkg_header(uint8_t *header, size_t headerSize){\n\tstruct mtkupg_header *hdr = (struct mtkupg_header *)header;\n\n\tif( !strncmp(hdr->vendor_magic, HISENSE_PKG_MAGIC, strlen(HISENSE_PKG_MAGIC)) ){\n\t\tprintf(\"[+] Found HISENSE Package\\n\");\n\t\treturn 1;\n\t}\n\tif( !strncmp(hdr->vendor_magic, SHARP_PKG_MAGIC, strlen(SHARP_PKG_MAGIC)) ){\n\t\tprintf(\"[+] Found SHARP Package\\n\");\n\t\tmtkpkg_variant_flags |= SHARP;\n\t\treturn 1;\n\t}\n\tif( !strncmp(hdr->vendor_magic, TPV_PKG_MAGIC, strlen(TPV_PKG_MAGIC)) ||\n\t\t!strncmp(hdr->vendor_magic, TPV_PKG_MAGIC2,strlen(TPV_PKG_MAGIC2))\n\t){\n\t\tprintf(\"[+] Found PHILIPS(TPV) Package\\n\");\n\t\treturn 1;\n\t}\n\n\tif( !strncmp(hdr->vendor_magic, PHILIPS_PKG_MAGIC, strlen(PHILIPS_PKG_MAGIC))\n\t || !strncmp(hdr->vendor_magic, PHILIPS_PKG_MAGIC2, strlen(PHILIPS_PKG_MAGIC2))\n\t){\n\t\tprintf(\"[+] Found PHILIPS Package\\n\");\n\t\treturn 1;\n\t}\n\n\tif( !strncmp(hdr->mtk_magic, MTK_FIRMWARE_MAGIC, strlen(MTK_FIRMWARE_MAGIC)) ){\n\t\tprintf(\"[+] Found UNKNOWN Package (Magic: '%.*s')\\n\",\n\t\t\tmember_size(struct mtkupg_header, vendor_magic),\n\t\t\thdr->vendor_magic\n\t\t);\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\nint compare_content_header(uint8_t *header, size_t headerSize){\n\tstruct mtkpkg_data *data = (struct mtkpkg_data *)header;\n\tif ( !strncmp(data->header.mtk_reserved, MTK_RESERVED_MAGIC, strlen(MTK_RESERVED_MAGIC)) ){\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nbool is_known_partition(struct mtkpkg *pak){\n\tconst char *likelyPartitionNames[] = {\n\t\t\"cfig\",\n\t\t\"ixml\",\n\t\t\"tzbp\",\n\t\tNULL\n\t};\n\n\tconst char **curPartName = likelyPartitionNames;\n\tfor(int nameIndex=0; *curPartName != NULL; nameIndex++){\n\t\tif(!strncmp(pak->header.pakName, *curPartName, sizeof(pak->header.pakName))){\n\t\t\treturn true;\n\t\t}\n\t\tcurPartName++;\n\t}\n\treturn false;\n}\n\nMFILE *is_mtk_pkg(const char *pkgfile){\n\tsetKeyFile_MTK();\n\n\tMFILE *mf = mopen(pkgfile, O_RDONLY);\n\tif(!mf){\n\t\terr_exit(\"Cannot open file %s\\n\", pkgfile);\n\t}\n\n\tuint8_t *data = mdata(mf, uint8_t);\n\tvoid *decryptedHeader = NULL;\n\tKeyPair *headerKey = NULL;\n\n\tdo {\n\t\tif((headerKey = find_AES_key(data, UPG_HEADER_SIZE, compare_pkg_header, KEY_CBC, (void **)&decryptedHeader, 0)) != NULL){\n\t\t\tbreak;\n\t\t}\n\n\t\t/* It failed, but we want to check for Philips.\n\t\t * Philips has an additional 0x80 header before the normal PKG one\n\t\t */\n\t\tif((headerKey = find_AES_key(data + PHILIPS_HEADER_SIZE, UPG_HEADER_SIZE, compare_pkg_header, KEY_CBC, (void **)&decryptedHeader, 0)) != NULL){\n\t\t\tmtkpkg_variant_flags |= PHILIPS;\n\t\t}\n\t} while(0);\n\n\tif(headerKey != NULL){\n\t\twas_decrypted = true;\n\t\tmemcpy(&packageHeader, decryptedHeader, sizeof(packageHeader));\n\t\tfree(headerKey);\n\t\treturn mf;\n\t}\n\n\t/* No AES key found to decrypt the header. Try to check if it's a MTK PKG anyways\n\t * This method can return false for valid packages as the order of partitions isn't fixed\n\t */\n\n\t/* First pak doesn't have extended fields */\n\tstruct mtkpkg *firstPak = (struct mtkpkg *)(data + sizeof(struct mtkupg_header));\n\tif(is_known_partition(firstPak))\n\t\treturn mf;\n\n\tfirstPak = (struct mtkpkg *)(data + SIZEOF_OLD_HEADER);\n\tif(is_known_partition(firstPak)){\n\t\tmtkpkg_variant_flags = OLD;\n\t\treturn mf;\n\t}\n\n\tfirstPak = (struct mtkpkg *)(data + SIZEOF_OLD_HEADER + PHILIPS_HEADER_SIZE);\n\tif(is_known_partition(firstPak)){\n\t\tmtkpkg_variant_flags = OLD | PHILIPS;\n\t\treturn mf;\n\t}\n\n\tfirstPak = (struct mtkpkg *)(data + SIZEOF_THOMPSON_HEADER);\n\tif(is_known_partition(firstPak)){\n\t\tmtkpkg_variant_flags = NEW | THOMPSON;\n\t\treturn mf;\n\t}\n\n\tmclose(mf);\n\treturn NULL;\n}\n\n#define SIZEOF_FIRM_HEADERS 0x90\n\nMFILE *is_firm_image(const char *pkg){\n\tMFILE *mf = mopen(pkg, O_RDONLY);\n\tif(!mf){\n\t\terr_exit(\"Cannot open file %s\\n\", pkg);\n\t}\n\n\tif(msize(mf) < (SIZEOF_FIRM_HEADERS + 16)){\n\t\tmclose(mf);\n\t\treturn NULL;\n\t}\n\n\tif(is_lzhs_mem(mf, SIZEOF_FIRM_HEADERS)){\n\t\treturn mf;\n\t}\n\tmclose(mf);\n\treturn NULL;\n}\n\nint extract_firm_image(MFILE *mf){\n\treturn process_lzhs_segment(mf, SIZEOF_FIRM_HEADERS, \"firm\");\n}\n\nMFILE *is_lzhs_fs(const char *pkg){\n\tMFILE *mf = mopen(pkg, O_RDONLY);\n\tif(!mf){\n\t\terr_exit(\"Cannot open file %s\\n\", pkg);\n\t}\n\n\tuint8_t *data = mdata(mf, uint8_t);\n\n\toff_t start = MTK_EXT_LZHS_OFFSET;\n\tif(is_nfsb_mem(mf, SHARP_PKG_HEADER_SIZE)){\n\t\tstart += SHARP_PKG_HEADER_SIZE;\n\t}\n\n\tif(msize(mf) < (start + sizeof(struct lzhs_header))){\n\t\tgoto fail;\n\t}\n\n\tif(\n\t\tis_lzhs_mem(mf, start) &&\n\t\tis_lzhs_mem(mf, start + sizeof(struct lzhs_header)) &&\n\t\t// First LZHS header contains number of segment in checksum. Make sure that it is the first segment\n\t\t((struct lzhs_header *)&data[start])->checksum == 1\n\t){\n\t\treturn mf;\n\t}\n\n\tfail:\n\t\tmclose(mf);\n\t\treturn NULL;\n}\n\n/* Arguments passed to the thread function */\nstruct thread_arg {\n\tMFILE *mf;\n\toff_t offset;\n\tchar *filename;\n\tuint blockNo;\n};\n\nvoid process_block(struct thread_arg *arg){\n\tprintf(\"[+] Extracting %u...\\n\", arg->blockNo);\n\tuint8_t out_checksum = 0x00;\n\tcursor_t *out_cur = lzhs_decode(arg->mf, arg->offset, NULL, &out_checksum);\n\tif(out_cur == NULL || (intptr_t)out_cur < 0){\n\t\terr_exit(\"LZHS decode failed\\n\");\n\t}\n\n\tMFILE *out = mfopen(arg->filename, \"w+\");\n\tif(!out){\n\t\terr_exit(\"mfopen failed for file '%s'\\n\", arg->filename);\n\t}\n\tmfile_map(out, out_cur->size);\n\tmemcpy(\n\t\tmdata(out, void),\n\t\tout_cur->ptr,\n\t\tout_cur->size\n\t);\n\tmclose(out);\n\tmunmap(out_cur->ptr, out_cur->size);\n\tfree(out_cur);\n\n\tfree(arg->filename);\n\tfree(arg);\n}\n\n/*\n * Hisense (or Mediatek?) uses an ext4 filesystem splitted in chunks, compressed with LZHS\n * They use 2 LZHS header for each chunk\n * The first header contains the chunk number, and the compressed size includes the outer lzhs header (+16)\n * The second header contains the actual data\n */\nvoid extract_lzhs_fs(MFILE *mf, const char *dest_file, config_opts_t *config_opts){\n\tint is_sharp = 0;\n\tuint8_t *data = mdata(mf, uint8_t);\n\tif(is_nfsb_mem(mf, SHARP_PKG_HEADER_SIZE)){\n\t\tdata += SHARP_PKG_HEADER_SIZE;\n\t\tis_sharp = 1;\n\t}\n\n\tFILE *out_file = fopen(dest_file, \"w+\");\n\tif(!out_file){\n\t\terr_exit(\"Cannot open %s for writing\\n\", dest_file);\n\t}\n\n\tchar *dir = my_dirname(dest_file);\n\tchar *file = my_basename(dest_file);\n\tchar *base = remove_ext(file);\n\n\tchar *tmpdir;\n\tasprintf(&tmpdir, \"%s/tmp\", dir);\n\tcreateFolder(tmpdir);\n\n\tprintf(\"Copying 0x%08X bytes\\n\", MTK_EXT_LZHS_OFFSET);\n\n\t/* Copy first MB as-is (uncompressed) */\n\tfwrite (\n\t\tdata,\n\t\tMTK_EXT_LZHS_OFFSET,\n\t\t1,\n\t\tout_file\n\t);\n\n\tdata += MTK_EXT_LZHS_OFFSET;\n\n\tint nThreads = sysconf(_SC_NPROCESSORS_ONLN);\n\tprintf(\"[+] Max threads: %d\\n\", nThreads);\n\tthreadpool thpool = thpool_init(nThreads);\n\n\tuint segNo = 0;\n\twhile(moff(mf, data) < msize(mf)){\n\t\tstruct lzhs_header *main_hdr = (struct lzhs_header *)data;\n\t\tstruct lzhs_header *seg_hdr = (struct lzhs_header *)(data + sizeof(*main_hdr));\n\n\t\tprintf(\"\\n[0x%08X] segment #%u (compressed='%u bytes', uncompressed='%u bytes')\\n\",\n\t\t\tmoff(mf, main_hdr),\n\t\t\tmain_hdr->checksum,\n\t\t\tseg_hdr->compressedSize, seg_hdr->uncompressedSize);\n\n\t\tchar *outSeg;\n\t\tasprintf(&outSeg, \"%s/%s.%d\", tmpdir, base, (segNo++) + 1);\n\t\tstruct thread_arg *arg = calloc(1, sizeof(struct thread_arg));\n\t\targ->mf = mf;\n\t\targ->offset = moff(mf, seg_hdr);\n\t\targ->filename = outSeg;\n\t\targ->blockNo = main_hdr->checksum;\n\n\t\tthpool_add_work(thpool, (void *)process_block, arg);\n\n\t\tuint pad;\n\t\tpad = (pad = (seg_hdr->compressedSize % 16)) == 0 ? 0 : (16 - pad);\n\n\t\tdata += (\n\t\t\tsizeof(*main_hdr) + sizeof(*seg_hdr) +\n\t\t\tseg_hdr->compressedSize +\n\t\t\tpad\n\t\t);\n\t}\n\n\tthpool_wait(thpool);\n\tthpool_destroy(thpool);\n\n\tuint i;\n\tfor(i=1; i<=segNo; i++){\n\t\tprintf(\"[+] Joining Segment %u\\n\", i);\n\t\tchar *outSeg;\n\t\tasprintf(&outSeg, \"%s/%s.%u\", tmpdir, base, i);\n\n\t\tMFILE *seg = mopen(outSeg, O_RDONLY);\n\t\tif(seg) {\n\t\t\tfwrite(mdata(seg, void), msize(seg), 1, out_file);\n\t\t\tmclose(seg);\n\t\t} else {\n\t\t\tprintf(\"A package wasn't written to disk because of a memory allocation failure\\n\");\n\t\t}\n\n\t\tunlink(outSeg);\n\t\tfree(outSeg);\n\t}\n\n\trmrf(tmpdir);\n\tfree(tmpdir);\n\n\tfclose(out_file);\n\n\tfree(dir);\n\tfree(file);\n\tfree(base);\n\n\tif(is_sharp){\n\t\thandle_file(dest_file, config_opts);\n\t}\n}\n\nvoid print_pkg_header(struct mtkupg_header *hdr){\n\thexdump(hdr, sizeof(*hdr));\n\n\tprintf(\"======== Firmware Info ========\\n\");\n\tprintf(\"| Product Name: %s\\n\", hdr->product_name);\n\tprintf(\"| Firmware ID : %.*s\\n\",\n\t\tmember_size(struct mtkupg_header, vendor_magic) +\n\t\tmember_size(struct mtkupg_header, mtk_magic) +\n\t\tmember_size(struct mtkupg_header, vendor_info),\n\t\thdr->vendor_magic\n\t);\n\tprintf(\"| File Size: %u bytes\\n\", hdr->fileSize);\n\tprintf(\"| Platform Type: 0x%02X\\n\", hdr->platform);\n\tprintf(\"======== Firmware Info ========\\n\");\n}\n\nstatic off_t get_mtkpkg_offset(){\n\tif((mtkpkg_variant_flags & THOMPSON) == THOMPSON){\n\t\treturn SIZEOF_THOMPSON_HEADER;\n\t}\n\n\toff_t offset = 0;\n\tif((mtkpkg_variant_flags & NEW) == NEW){\n\t\toffset += sizeof(struct mtkupg_header);\n\t} else if((mtkpkg_variant_flags & OLD) == OLD){\n\t\toffset += SIZEOF_OLD_HEADER;\n\t}\n\n\tif((mtkpkg_variant_flags & PHILIPS) == PHILIPS){\n\t\toffset += PHILIPS_HEADER_SIZE;\n\t}\n\n\treturn offset;\n}\n\nvoid extract_mtk_pkg(const char *pkgFile, config_opts_t *config_opts){\n\tMFILE *mf = mopen_private(pkgFile, O_RDONLY);\n\tmprotect(mf->pMem, msize(mf), PROT_READ | PROT_WRITE);\n\n\toff_t offset = get_mtkpkg_offset();\n\tuint8_t *data = mdata(mf, uint8_t) + offset;\n\n\tchar *file_name = my_basename(mf->path);\n\tchar *file_base = remove_ext(file_name);\n\n\tstruct mtkupg_header *hdr = (was_decrypted) ? &packageHeader : NULL;\n\tif(hdr != NULL)\n\t\tprint_pkg_header(hdr);\n\n\tif(hdr != NULL){\n\t\t// Use product name for now (version would be better)\n\t\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, hdr->product_name);\n\t} else {\n\t\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, file_base);\n\t}\n\tcreateFolder(config_opts->dest_dir);\n\n\tKeyPair *dataKey = NULL;\n\n\tint pakNo;\n\tfor(pakNo=0; moff(mf, data) < msize(mf); pakNo++){\n\t\tstruct mtkpkg *pak = (struct mtkpkg *)data;\n\t\tif((mtkpkg_variant_flags & PHILIPS) == PHILIPS && moff(mf, data) + PHILIPS_SIGNATURE_SIZE == msize(mf)){\n\t\t\tprintf(\"-- RSA 2048 Signature --\\n\");\n\t\t\thexdump(data, PHILIPS_SIGNATURE_SIZE);\n\t\t\t//Philips RSA-2048 signature\n\t\t\tbreak;\n\t\t}\n\n\t\tsize_t cryptedHeaderSize = ((mtkpkg_variant_flags & NEW) == NEW) ? sizeof(pak->content.header) : 0;\n\n\t\t/* Skip pak header and crypted header */\n\t\tdata += sizeof(pak->header) + cryptedHeaderSize;\n\n\t\tuint8_t *pkgData = (uint8_t *)&(pak->content.header);\n\t\tsize_t dataSize = sizeof(pak->content.header);\n\t\tsize_t pkgSize = pak->header.pakSize;\n\t\tif(pkgSize == 0){\n\t\t\tgoto save_file;\n\t\t}\n\n\t\tif((pak->header.flags & PAK_FLAG_ENCRYPTED) == PAK_FLAG_ENCRYPTED){\n\t\t\tdataSize += pak->header.pakSize;\n\t\t}\n\n#pragma region FindAesKey\n\t\tuint8_t *decryptedPkgData = NULL;\n\n\t\tif(was_decrypted){\n\t\t\tif(dataKey == NULL){\n\t\t\t\tdataKey = find_AES_key(\n\t\t\t\t\tpkgData,\n\t\t\t\t\tdataSize,\n\t\t\t\t\tcompare_content_header,\n\t\t\t\t\tKEY_CBC,\n\t\t\t\t\t(void **)&decryptedPkgData,\n\t\t\t\t\t1\n\t\t\t\t);\n\t\t\t\tint success = dataKey != NULL;\n\t\t\t\tif(success){\n\t\t\t\t\t/* Copy decrypted data */\n\t\t\t\t\tmemcpy(pkgData, decryptedPkgData, dataSize);\n\t\t\t\t\tfree(decryptedPkgData);\n\t\t\t\t} else if(was_decrypted) {\n\t\t\t\t\t/* Try to decrypt by using vendorMagic repeated 4 times, ivec 0 */\n\t\t\t\t\tdo {\n\t\t\t\t\t\tAES_KEY aesKey;\n\t\t\t\t\t\tuint8_t keybuf[16];\n\t\t\t\t\t\tuint i;\n\t\t\t\t\t\tfor(i=0; i<4; i++){\n\t\t\t\t\t\t\tmemcpy(&keybuf[4 * i], hdr->vendor_magic, sizeof(uint32_t));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tAES_set_decrypt_key((uint8_t *)&keybuf, 128, &aesKey);\n\n\t\t\t\t\t\tdataKey = calloc(1, sizeof(KeyPair)); //also fills ivec with zeros\n\t\t\t\t\t\tmemcpy(&(dataKey->key), &aesKey, sizeof(aesKey));\n\n\t\t\t\t\t\tuint8_t iv_tmp[16];\n\t\t\t\t\t\tmemcpy(&iv_tmp, &(dataKey->ivec), sizeof(iv_tmp));\n\t\t\t\t\t\tAES_cbc_encrypt(\n\t\t\t\t\t\t\tpkgData, pkgData,\n\t\t\t\t\t\t\tdataSize, &(dataKey->key),\n\t\t\t\t\t\t\t(void *)&iv_tmp, AES_DECRYPT\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tsuccess = compare_content_header(pkgData, sizeof(struct mtkpkg_data));\n\t\t\t\t\t} while(0);\n\t\t\t\t}\n\t\t\t\tif(!success){\n\t\t\t\t\tif((pak->header.flags & PAK_FLAG_ENCRYPTED) == PAK_FLAG_ENCRYPTED){\n\t\t\t\t\t\tprintf(\"[-] Couldn't decrypt data!\\n\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprintf(\"[-] Couldn't decrypt header!\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t#pragma endregion\n\t\t\t\tuint8_t iv_tmp[16];\n\t\t\t\tmemcpy(&iv_tmp, &(dataKey->ivec), sizeof(iv_tmp));\n\t\t\t\tAES_cbc_encrypt(\n\t\t\t\t\tpkgData, pkgData,\n\t\t\t\t\tdataSize, &(dataKey->key),\n\t\t\t\t\t(void *)&iv_tmp, AES_DECRYPT\n\t\t\t\t);\n\t\t\t\tint success = compare_content_header(pkgData, sizeof(struct mtkpkg_data));\n\t\t\t\tif(!success){\n\t\t\t\t\tfprintf(stderr, \"[!] WARNING: MTK Crypted header not found, continuing anyways...\\n\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif((mtkpkg_variant_flags & NEW) == NEW){\n\t\t\t// Skip the mtk header (reserved inc)\n\t\t\tpkgData += sizeof(struct mtkpkg_crypted_header);\n\t\t}\n\n\t\tprintf(\"\\nPAK #%u %s (name='%s', offset='0x%lx', size='%u bytes'\",\n\t\t\tpakNo + 1,\n\t\t\t((pak->header.flags & PAK_FLAG_ENCRYPTED) == PAK_FLAG_ENCRYPTED) ? \"[ENCRYPTED]\" : \"\",\n\t\t\tpak->header.pakName,\n\t\t\tmoff(mf, data),\n\t\t\tpak->header.pakSize\n\t\t);\n\n\t\tstruct mtkpkg_plat *ext = (struct mtkpkg_plat *)pkgData;\n\n\t\t/* Parse the fields at the start of pkgData, and skip them */\n\t\tif(!strncmp(ext->platform, MTK_PAK_MAGIC, strlen(MTK_PAK_MAGIC))){\n\t\t\tuint8_t *extData = (uint8_t *)&(ext->otaID_len);\n\t\t\t/* otaID is optional. if we have it, it's preceded by its length. If we don't have it, we have the iPAD magic instead */\n\t\t\tint has_otaID = strncmp(extData, MTK_PAD_MAGIC, strlen(MTK_PAD_MAGIC)) != 0;\n\t\t\tif(has_otaID){\n\t\t\t\tprintf(\", platform='%s', otaid='%s'\", ext->platform, ext->otaID);\n\t\t\t\tif(pakNo == 1 && hdr == NULL){\n\t\t\t\t\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, ext->otaID);\n\t\t\t\t\tcreateFolder(config_opts->dest_dir);\n\t\t\t\t}\n\t\t\t} else if(pakNo == 1 && hdr == NULL){\n\t\t\t\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, file_base);\n\t\t\t\tcreateFolder(config_opts->dest_dir);\n\t\t\t}\n\n\t\t\t/* Skip the headers to get to the data */\n\t\t\tuint skip = sizeof(*ext);\n\t\t\tif(has_otaID){\n\t\t\t\tskip += ext->otaID_len;\n\t\t\t}\n\t\t\tif(skip < MTK_EXTHDR_SIZE){\n\t\t\t\tskip += (MTK_EXTHDR_SIZE - skip);\n\t\t\t}\n\n\t\t\tpkgData += skip;\n\t\t\tpkgSize -= skip;\n\t\t}\n\n\t\tsave_file:\n\t\tprintf(\")\\n\");\n\n\t\tchar *dest_path = NULL;\n\t\tasprintf(&dest_path, \"%s/%.*s.pak\",\n\t\t\tconfig_opts->dest_dir,\n\t\t\tmember_size(struct mtkpkg_header, pakName), pak->header.pakName\n\t\t);\n\n\t\tMFILE *out = mfopen(dest_path, \"w+\");\n\t\tif(!out){\n\t\t\terr_exit(\"Cannot open %s for writing\\n\", dest_path);\n\t\t}\n\n\t\tprintf(\"Saving partition (%s) to file %s\\n\\n\", pak->header.pakName, dest_path);\n\n\t\tif(pkgSize == 0)\n\t\t\tgoto saved_file;\n\n\t\tmfile_map(out, pkgSize);\n\t\tmwrite(pkgData, pkgSize, 1, out);\n\n\t\tsaved_file:\n\t\tmclose(out);\n\n\t\tif(dest_path != NULL && pkgSize != 0){\n\t\t\thandle_file(dest_path, config_opts);\n\t\t}\n\t\tif(dest_path != NULL){\n\t\t\tfree(dest_path);\n\t\t}\n\n\t\tdata += pak->header.pakSize;\n\t}\n\n\tif(dataKey != NULL){\n\t\tfree(dataKey);\n\t}\n\n\tfree(file_name);\n\tfree(file_base);\n\tmclose(mf);\n}\n"
  },
  {
    "path": "src/mfile.c",
    "content": "/**\n * mmap file wrapper\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdbool.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <errno.h>\n#include \"mfile.h\"\n\n#include \"common.h\"\n#include \"util.h\"\n\n#define PERMS_DEFAULT (mode_t)0666\n\n/*\n * Creates a new mfile structure\n */\ninline MFILE *mfile_new(){\n\tMFILE *mem = calloc(1, sizeof(MFILE));\n\treturn mem;\n}\n\n/*\n * Updates size and path to a file\n */\nint _mfile_update_info(MFILE *file, const char *path){\n\tif(path){\n\t\tif(file->path)\n\t\t\tfree(file->path);\n\t\tfile->path = strdup(path);\n\t}\n\tif(stat(file->path, &(file->statBuf)) < 0)\n\t\treturn -1;\n\treturn 0;\n}\n\nvoid mfile_flush(void *mem, size_t length){\n\tmsync(mem, length, MS_INVALIDATE);\n\t//madvise(mem, length, MADV_REMOVE);\n}\n\n/*\n * Wrapper to mmap\n */\nvoid *_mfile_map(MFILE *file, size_t mapSize, int mapFlags){\n\tif(msize(file) < mapSize){\n\t\tlseek(file->fd, mapSize-1, SEEK_SET);\n\t\tuint8_t buf = 0x00;\n\t\twrite(file->fd, &buf, 1);\n\t\tlseek(file->fd, 0, SEEK_SET);\n\t\t_mfile_update_info(file, NULL);\n\t}\n\tfile->pMem = mmap(0, mapSize, file->prot, mapFlags, file->fd, 0);\n\tif(file->pMem == MAP_FAILED){\n\t\terr_exit(\"mmap failed: %s (%d)\\n\", strerror(errno), errno);\n\t\treturn NULL;\n\t}\n\n\t// enable read ahead and trash previously read pages\n\tmadvise(file->pMem, mapSize, MADV_SEQUENTIAL);\n\treturn file->pMem;\n}\n\ninline void *mfile_map(MFILE *file, size_t mapSize){\n\treturn _mfile_map(file, mapSize, MAP_SHARED);\n}\n\ninline void *mfile_map_private(MFILE *file, size_t mapSize){\n\treturn _mfile_map(file, mapSize, MAP_PRIVATE);\n}\n\n/*\n * Opens and maps a file with open\n */\nMFILE *_mopen(const char *path, int oflags, int mapFlags){\n\tMFILE *file = mfile_new();\n\tfile->fd = open(path, oflags, PERMS_DEFAULT);\n\tif(file->fd < 0){\n\t\tgoto e0_ret;\n\t}\n\n\tif(_mfile_update_info(file, path) < 0)\n\t\tgoto e1_ret;\n\n\tif((oflags & O_ACCMODE) == O_RDONLY) {\n\t\tfile->prot = PROT_READ;\n\t} else if((oflags & O_ACCMODE) == O_WRONLY) {\n\t\tfile->prot = PROT_WRITE;\n\t} else if((oflags & O_ACCMODE) == O_RDWR) {\n\t\tfile->prot = PROT_READ | PROT_WRITE;\n\t}\n\n\tsize_t fileSz = msize(file);\n\tif(fileSz > 0){\n\t\tif(_mfile_map(file, fileSz, mapFlags) == MAP_FAILED){\n\t\t\tgoto e1_ret;\n\t\t}\n\t}\n\treturn file;\n\n\te1_ret:\n\t\tclose(file->fd);\n\te0_ret:\n\t\tif(file->path)\n\t\t\tfree(file->path);\n\t\tfree(file);\n\t\treturn NULL;\n}\n\ninline MFILE *mopen(const char *path, int oflags){\n\treturn _mopen(path, oflags, MAP_SHARED);\n}\n\ninline MFILE *mopen_private(const char *path, int oflags){\n\treturn _mopen(path, oflags, MAP_PRIVATE);\n}\n\nint mgetc(MFILE *stream){\n\tif(UNLIKELY(stream->offset >= msize(stream)))\n\t\treturn EOF;\n\treturn (unsigned int)(*(&((uint8_t *)(stream->pMem))[stream->offset++]));\n}\n\nint mputc(int c, MFILE *stream){\n\tif(UNLIKELY(stream->offset >= msize(stream)))\n\t\treturn EOF;\n\t((uint8_t *)(stream->pMem))[stream->offset] = (uint8_t)c;\n\tstream->offset++;\n\treturn c;\n}\n\ninline int cgetc(cursor_t *stream){\n\tif(UNLIKELY(stream->offset >= stream->size))\n\t\treturn EOF;\n\treturn (unsigned int)(\n\t\t*(&(\n\t\t\t((unsigned char *)(stream->ptr))[stream->offset++]\n\t\t))\n\t);\n}\n\nint cputc(int c, cursor_t *stream){\n\tif(UNLIKELY(stream->offset >= stream->size))\n\t\treturn EOF;\n\t((unsigned char *)(stream->ptr))[stream->offset++] = (unsigned char)c;\n\treturn c;\n}\n\n/*\n * Closes an opened file and frees the structure\n */\nint mclose(MFILE *mfile){\n\tif(!mfile || mfile->fd < 0 || !mfile->pMem || mfile->statBuf.st_size <= 0)\n\t\treturn -1;\n\tif(munmap(mfile->pMem, mfile->statBuf.st_size) < 0)\n\t\treturn -2;\n\tfree(mfile->path);\n\tif(mfile->fh != NULL){\n\t\tfclose(mfile->fh);\n\t\tmfile->fd = 0;\n\t} else {\n\t\tclose(mfile->fd);\n\t}\n\tfree(mfile);\n\tmfile = NULL;\n\treturn 0;\n}\n\n/*\n * Opens and maps a file with fopen\n */\nMFILE *_mfopen(const char *path, const char *mode, int mapFlags){\n\tMFILE *file = mfile_new();\n\n\tfile->fh = fopen(path, mode);\n\tif(file->fh == NULL){\n\t\tgoto e0_ret;\n\t}\n\tfile->fd = fileno(file->fh);\n\n\tif(_mfile_update_info(file, path) < 0)\n\t\tgoto e1_ret;\n\n\tif(strstr(mode, \"r\") != NULL || strstr(mode, \"+\") != NULL){\n\t\tfile->prot |= PROT_READ;\n\t}\n\tif(strstr(mode, \"w\") != NULL){\n\t\tfile->prot |= PROT_WRITE;\n\t}\n\n\tsize_t fileSz = msize(file);\n\tif(fileSz > 0){\n\t\tif(_mfile_map(file, fileSz, mapFlags) == MAP_FAILED){\n\t\t\tgoto e1_ret;\n\t\t}\n\t}\n\n\treturn file;\n\n\te1_ret:\n\t\tfclose(file->fh);\n\te0_ret:\n\t\tfree(file);\n\t\treturn NULL;\n}\n\ninline MFILE *mfopen(const char *path, const char *mode){\n\treturn _mfopen(path, mode, MAP_SHARED);\n}\n\ninline MFILE *mfopen_private(const char *path, const char *mode){\n\treturn _mfopen(path, mode, MAP_PRIVATE);\n}\n"
  },
  {
    "path": "src/minigzip.c",
    "content": "/* minigzip.c -- simulate gzip using the zlib compression library\n * Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly.\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/*\n * minigzip is a minimal implementation of the gzip utility. This is\n * only an example of using zlib and isn't meant to replace the\n * full-featured gzip. No attempt is made to deal with file systems\n * limiting names to 14 or 8+3 characters, etc... Error checking is\n * very limited. So use minigzip only for testing; use gzip for the\n * real thing. On MSDOS, use only on file names without extension\n * or in pipe mode.\n */\n\n/* @(#) $Id$ */\n\n#include \"zlib.h\"\n#include <stdio.h>\n\n#ifdef STDC\n#  include <string.h>\n#  include <stdlib.h>\n#endif\n\n#ifdef USE_MMAP\n#  include <sys/types.h>\n#  include <sys/mman.h>\n#  include <sys/stat.h>\n#endif\n\n#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)\n#  include <fcntl.h>\n#  include <io.h>\n#  ifdef UNDER_CE\n#    include <stdlib.h>\n#  endif\n#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)\n#else\n#  define SET_BINARY_MODE(file)\n#endif\n\n#ifdef _MSC_VER\n#  define snprintf _snprintf\n#endif\n\n#ifdef VMS\n#  define unlink delete\n#  define GZ_SUFFIX \"-gz\"\n#endif\n#ifdef RISCOS\n#  define unlink remove\n#  define GZ_SUFFIX \"-gz\"\n#  define fileno(file) file->__file\n#endif\n#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os\n#  include <unix.h> /* for fileno */\n#endif\n\n#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)\n#ifndef WIN32 /* unlink already in stdio.h for WIN32 */\n  extern int unlink OF((const char *));\n#endif\n#endif\n\n#if defined(UNDER_CE)\n#  include <windows.h>\n#  define perror(s) pwinerror(s)\n\n/* Map the Windows error number in ERROR to a locale-dependent error\n   message string and return a pointer to it.  Typically, the values\n   for ERROR come from GetLastError.\n\n   The string pointed to shall not be modified by the application,\n   but may be overwritten by a subsequent call to strwinerror\n\n   The strwinerror function does not change the current setting\n   of GetLastError.  */\n\nstatic char *strwinerror (error)\n     DWORD error;\n{\n    static char buf[1024];\n\n    wchar_t *msgbuf;\n    DWORD lasterr = GetLastError();\n    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM\n        | FORMAT_MESSAGE_ALLOCATE_BUFFER,\n        NULL,\n        error,\n        0, /* Default language */\n        (LPVOID)&msgbuf,\n        0,\n        NULL);\n    if (chars != 0) {\n        /* If there is an \\r\\n appended, zap it.  */\n        if (chars >= 2\n            && msgbuf[chars - 2] == '\\r' && msgbuf[chars - 1] == '\\n') {\n            chars -= 2;\n            msgbuf[chars] = 0;\n        }\n\n        if (chars > sizeof (buf) - 1) {\n            chars = sizeof (buf) - 1;\n            msgbuf[chars] = 0;\n        }\n\n        wcstombs(buf, msgbuf, chars + 1);\n        LocalFree(msgbuf);\n    }\n    else {\n        sprintf(buf, \"unknown win32 error (%ld)\", error);\n    }\n\n    SetLastError(lasterr);\n    return buf;\n}\n\nstatic void pwinerror (s)\n    const char *s;\n{\n    if (s && *s)\n        fprintf(stderr, \"%s: %s\\n\", s, strwinerror(GetLastError ()));\n    else\n        fprintf(stderr, \"%s\\n\", strwinerror(GetLastError ()));\n}\n\n#endif /* UNDER_CE */\n\n#ifndef GZ_SUFFIX\n#  define GZ_SUFFIX \".gz\"\n#endif\n#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)\n\n#define BUFLEN      16384\n#define MAX_NAME_LEN 1024\n\n#ifdef MAXSEG_64K\n#  define local static\n   /* Needed for systems with limitation on stack size. */\n#else\n#  define local\n#endif\n\n#ifdef Z_SOLO\n/* for Z_SOLO, create simplified gz* functions using deflate and inflate */\n\n#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)\n#  include <unistd.h>       /* for unlink() */\n#endif\n\nvoid *myalloc OF((void *, unsigned, unsigned));\nvoid myfree OF((void *, void *));\n\nvoid *myalloc(q, n, m)\n    void *q;\n    unsigned n, m;\n{\n    q = Z_NULL;\n    return calloc(n, m);\n}\n\nvoid myfree(q, p)\n    void *q, *p;\n{\n    q = Z_NULL;\n    free(p);\n}\n\ntypedef struct gzFile_s {\n    FILE *file;\n    int write;\n    int err;\n    char *msg;\n    z_stream strm;\n} *gzFile;\n\ngzFile gzopen OF((const char *, const char *));\ngzFile gzdopen OF((int, const char *));\ngzFile gz_open OF((const char *, int, const char *));\n\ngzFile gzopen(path, mode)\nconst char *path;\nconst char *mode;\n{\n    return gz_open(path, -1, mode);\n}\n\ngzFile gzdopen(fd, mode)\nint fd;\nconst char *mode;\n{\n    return gz_open(NULL, fd, mode);\n}\n\ngzFile gz_open(path, fd, mode)\n    const char *path;\n    int fd;\n    const char *mode;\n{\n    gzFile gz;\n    int ret;\n\n    gz = malloc(sizeof(struct gzFile_s));\n    if (gz == NULL)\n        return NULL;\n    gz->write = strchr(mode, 'w') != NULL;\n    gz->strm.zalloc = myalloc;\n    gz->strm.zfree = myfree;\n    gz->strm.opaque = Z_NULL;\n    if (gz->write)\n        ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);\n    else {\n        gz->strm.next_in = 0;\n        gz->strm.avail_in = Z_NULL;\n        ret = inflateInit2(&(gz->strm), 15 + 16);\n    }\n    if (ret != Z_OK) {\n        free(gz);\n        return NULL;\n    }\n    gz->file = path == NULL ? fdopen(fd, gz->write ? \"wb\" : \"rb\") :\n                              fopen(path, gz->write ? \"wb\" : \"rb\");\n    if (gz->file == NULL) {\n        gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));\n        free(gz);\n        return NULL;\n    }\n    gz->err = 0;\n    gz->msg = \"\";\n    return gz;\n}\n\nint gzwrite OF((gzFile, const void *, unsigned));\n\nint gzwrite(gz, buf, len)\n    gzFile gz;\n    const void *buf;\n    unsigned len;\n{\n    z_stream *strm;\n    unsigned char out[BUFLEN];\n\n    if (gz == NULL || !gz->write)\n        return 0;\n    strm = &(gz->strm);\n    strm->next_in = (void *)buf;\n    strm->avail_in = len;\n    do {\n        strm->next_out = out;\n        strm->avail_out = BUFLEN;\n        (void)deflate(strm, Z_NO_FLUSH);\n        fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);\n    } while (strm->avail_out == 0);\n    return len;\n}\n\nint gzread OF((gzFile, void *, unsigned));\n\nint gzread(gz, buf, len)\n    gzFile gz;\n    void *buf;\n    unsigned len;\n{\n    int ret;\n    unsigned got;\n    unsigned char in[1];\n    z_stream *strm;\n\n    if (gz == NULL || gz->write)\n        return 0;\n    if (gz->err)\n        return 0;\n    strm = &(gz->strm);\n    strm->next_out = (void *)buf;\n    strm->avail_out = len;\n    do {\n        got = fread(in, 1, 1, gz->file);\n        if (got == 0)\n            break;\n        strm->next_in = in;\n        strm->avail_in = 1;\n        ret = inflate(strm, Z_NO_FLUSH);\n        if (ret == Z_DATA_ERROR) {\n            gz->err = Z_DATA_ERROR;\n            gz->msg = strm->msg;\n            return 0;\n        }\n        if (ret == Z_STREAM_END)\n            inflateReset(strm);\n    } while (strm->avail_out);\n    return len - strm->avail_out;\n}\n\nint gzclose OF((gzFile));\n\nint gzclose(gz)\n    gzFile gz;\n{\n    z_stream *strm;\n    unsigned char out[BUFLEN];\n\n    if (gz == NULL)\n        return Z_STREAM_ERROR;\n    strm = &(gz->strm);\n    if (gz->write) {\n        strm->next_in = Z_NULL;\n        strm->avail_in = 0;\n        do {\n            strm->next_out = out;\n            strm->avail_out = BUFLEN;\n            (void)deflate(strm, Z_FINISH);\n            fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);\n        } while (strm->avail_out == 0);\n        deflateEnd(strm);\n    }\n    else\n        inflateEnd(strm);\n    fclose(gz->file);\n    free(gz);\n    return Z_OK;\n}\n\nconst char *gzerror OF((gzFile, int *));\n\nconst char *gzerror(gz, err)\n    gzFile gz;\n    int *err;\n{\n    *err = gz->err;\n    return gz->msg;\n}\n\n#endif\n\nchar *prog;\n\nvoid error            OF((const char *msg));\nvoid gz_compress      OF((FILE   *in, gzFile out));\n#ifdef USE_MMAP\nint  gz_compress_mmap OF((FILE   *in, gzFile out));\n#endif\nvoid gz_uncompress    OF((gzFile in, FILE   *out));\nvoid file_compress    OF((char  *file, char *mode));\nvoid file_uncompress  OF((char  *file));\n\n/* ===========================================================================\n * Display error message and exit\n */\nvoid error(msg)\n    const char *msg;\n{\n    fprintf(stderr, \"%s: %s\\n\", prog, msg);\n    exit(1);\n}\n\n/* ===========================================================================\n * Compress input to output then close both files.\n */\n\nvoid gz_compress(in, out)\n    FILE   *in;\n    gzFile out;\n{\n    local char buf[BUFLEN];\n    int len;\n    int err;\n\n#ifdef USE_MMAP\n    /* Try first compressing with mmap. If mmap fails (minigzip used in a\n     * pipe), use the normal fread loop.\n     */\n    if (gz_compress_mmap(in, out) == Z_OK) return;\n#endif\n    for (;;) {\n        len = (int)fread(buf, 1, sizeof(buf), in);\n        if (ferror(in)) {\n            perror(\"fread\");\n            exit(1);\n        }\n        if (len == 0) break;\n\n        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));\n    }\n    fclose(in);\n    if (gzclose(out) != Z_OK) error(\"failed gzclose\");\n}\n\n#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */\n\n/* Try compressing the input file at once using mmap. Return Z_OK if\n * if success, Z_ERRNO otherwise.\n */\nint gz_compress_mmap(in, out)\n    FILE   *in;\n    gzFile out;\n{\n    int len;\n    int err;\n    int ifd = fileno(in);\n    caddr_t buf;    /* mmap'ed buffer for the entire input file */\n    off_t buf_len;  /* length of the input file */\n    struct stat sb;\n\n    /* Determine the size of the file, needed for mmap: */\n    if (fstat(ifd, &sb) < 0) return Z_ERRNO;\n    buf_len = sb.st_size;\n    if (buf_len <= 0) return Z_ERRNO;\n\n    /* Now do the actual mmap: */\n    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);\n    if (buf == (caddr_t)(-1)) return Z_ERRNO;\n\n    /* Compress the whole file at once: */\n    len = gzwrite(out, (char *)buf, (unsigned)buf_len);\n\n    if (len != (int)buf_len) error(gzerror(out, &err));\n\n    munmap(buf, buf_len);\n    fclose(in);\n    if (gzclose(out) != Z_OK) error(\"failed gzclose\");\n    return Z_OK;\n}\n#endif /* USE_MMAP */\n\n/* ===========================================================================\n * Uncompress input to output then close both files.\n */\nvoid gz_uncompress(in, out)\n    gzFile in;\n    FILE   *out;\n{\n    local char buf[BUFLEN];\n    int len;\n    int err;\n\n    for (;;) {\n        len = gzread(in, buf, sizeof(buf));\n        if (len < 0) error (gzerror(in, &err));\n        if (len == 0) break;\n\n        if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {\n            error(\"failed fwrite\");\n        }\n    }\n    if (fclose(out)) error(\"failed fclose\");\n\n    if (gzclose(in) != Z_OK) error(\"failed gzclose\");\n}\n\n\n/* ===========================================================================\n * Compress the given file: create a corresponding .gz file and remove the\n * original.\n */\nvoid file_compress(file, mode)\n    char  *file;\n    char  *mode;\n{\n    local char outfile[MAX_NAME_LEN];\n    FILE  *in;\n    gzFile out;\n\n    if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {\n        fprintf(stderr, \"%s: filename too long\\n\", prog);\n        exit(1);\n    }\n\n#if !defined(NO_snprintf) && !defined(NO_vsnprintf)\n    snprintf(outfile, sizeof(outfile), \"%s%s\", file, GZ_SUFFIX);\n#else\n    strcpy(outfile, file);\n    strcat(outfile, GZ_SUFFIX);\n#endif\n\n    in = fopen(file, \"rb\");\n    if (in == NULL) {\n        perror(file);\n        exit(1);\n    }\n    out = gzopen(outfile, mode);\n    if (out == NULL) {\n        fprintf(stderr, \"%s: can't gzopen %s\\n\", prog, outfile);\n        exit(1);\n    }\n    gz_compress(in, out);\n\n    unlink(file);\n}\n\n\n/* ===========================================================================\n * Uncompress the given file and remove the original.\n */\nvoid file_uncompress(file)\n    char  *file;\n{\n    local char buf[MAX_NAME_LEN];\n    char *infile, *outfile;\n    FILE  *out;\n    gzFile in;\n    size_t len = strlen(file);\n\n    if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {\n        fprintf(stderr, \"%s: filename too long\\n\", prog);\n        exit(1);\n    }\n\n#if !defined(NO_snprintf) && !defined(NO_vsnprintf)\n    snprintf(buf, sizeof(buf), \"%s\", file);\n#else\n    strcpy(buf, file);\n#endif\n\n    if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {\n        infile = file;\n        outfile = buf;\n        outfile[len-3] = '\\0';\n    } else {\n        outfile = file;\n        infile = buf;\n#if !defined(NO_snprintf) && !defined(NO_vsnprintf)\n        snprintf(buf + len, sizeof(buf) - len, \"%s\", GZ_SUFFIX);\n#else\n        strcat(infile, GZ_SUFFIX);\n#endif\n    }\n    in = gzopen(infile, \"rb\");\n    if (in == NULL) {\n        fprintf(stderr, \"%s: can't gzopen %s\\n\", prog, infile);\n        exit(1);\n    }\n    out = fopen(outfile, \"wb\");\n    if (out == NULL) {\n        perror(file);\n        exit(1);\n    }\n\n    gz_uncompress(in, out);\n\n    unlink(infile);\n}\n\nchar *file_uncompress_origname(char *infile, char *path) {\n\tFILE *in, *out;\n\tgzFile gzin;\n\n\tchar *filename;\n\tint len = 0;\n\tin = fopen(infile, \"rb\");\n\tif (in == NULL) {\n\t\tprintf(\"Can't open %s\\n\", infile);\n\t\texit(1);\n\t}\n\tfseek(in, 10, SEEK_SET);\n\tchar c;\n\tdo {\n\t\tc = getc(in);\n\t\tlen++;\n\t} while (c != '\\x00');\t\t//calculate string length\n\tchar *dest = malloc(len + strlen(path));\t//allocate space for path+name\n\tmemset(dest, 0x0, strlen(dest));\n\tfilename = malloc(len);\t\t//allocate space for name\n\tfseek(in, 10, SEEK_SET);\n\tfread(filename, 1, len, in);\t//read filename\n\tprintf(\"Ungzipping file: %s\\n\", filename);\n\tfclose(in);\n\n\tstrcat(dest, path);\n\tstrcat(dest, filename);\n\n\tgzin = gzopen(infile, \"rb\");\n\tif (in == NULL) {\n\t\tfprintf(stderr, \"%s: can't gzopen %s\\n\", prog, infile);\n\t\texit(1);\n\t}\n\tout = fopen(dest, \"wb\");\n\tif (out == NULL) {\n\t\tperror(infile);\n\t\texit(1);\n\t}\n\n\tgz_uncompress(gzin, out);\n\t//unlink(infile);\n\treturn dest;\n\n}\n"
  },
  {
    "path": "src/partinfo.c",
    "content": "/**\n * LG partition table decoder\n * Original code from u-boot GPL package\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 20?? ???\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <ctype.h>\n#include <string.h>\n#include <sys/types.h>\n\n#include \"partinfo.h\"\n#include \"util.h\"\n\n#ifdef __CYGWIN__\n#    define lne \"\\r\\n\"\n#else\n#    define lne \"\\n\"\n#endif\n\n#define println()\t\t\t\tfprintf(destfile,lne)\n#include <errno.h>\n\nextern int errno;\n\nFILE *destfile;\n\n//structs\nstruct m_partmap_info m_partinfo;\nstruct p1_partmap_info p1_partinfo;\nstruct p2_partmap_info p2_partinfo;\n\nconst char *m_menu_partition_str[] = {\n\t\"MTD Partition Information ---------------------------------------------------------------------------------\",\n\t\"index[%d] - \",\n\t\"cur epk ver : 0x%06x\",\n\t\"old epk ver : 0x%06x\",\n\t\"\\t name\t= %s\",\n\t\"\\t offset\t= 0x%08x\",\n\t\"\\t size\t= 0x%08x\",\n\t\"\\t sw_ver = %d\",\n\t\"\\t filename = %s\",\n\t\"\\t MTD flags = %s\\n\"\n};\n\nconst char *m_menu_partition_info[] = {\n\t\"[%2d] \\\"%-12s\\\" : 0x%08x-0x%08x (0x%08x)\",\n\t\" %c%c%c%c\",\n\t\" : \\\"%-20s\\\"[%d] - 0x%06x : (%c/%c)\",\n\t\"[%2d] Empty\\n\"\n};\n\nstatic const char *p_menu_partition_str[] = {\n\t\"Partition Information ---------------------------------------------------------------------------------\",\n\t\"index[%d] - \",\n\t\"cur epk ver : 0x%06x\",\n\t\"old epk ver : 0x%06x\",\n\t\"\\t name\t= %s\",\n\t\"\\t offset\t= 0x%08x\",\n\t\"\\t size\t= 0x%08x\",\n\t\"\\t sw_ver = %d\",\n\t\"\\t filename = %s\",\n\t\"\\t flags = %s\\n\",\n\t\"\\t used = %c\",\n\t\"\\t valid = %c\"\n};\n\nstatic const char *p1_menu_partition_info[] = {\n\t\"[%2d] \\\"%-12s\\\" : 0x%08x-0x%08x (0x%08x)\",\n\t\" %c%c%c%c%c\",\n\t\" : \\\"%-20s\\\"[%d] - 0x%06x : (%c/%c)\",\n\t\"[%2d] Empty\\n\"\n};\n\nstatic const char *p2_menu_partition_info[] = {\n\t\"[%2d] \\\"%-12s\\\" : 0x%01x%08x-0x%01x%08x (0x%01x%08x)\",\n\t\" %c%c%c%c%c\",\n\t\" : \\\"%-20s\\\"[%d] - 0x%06x : (%c/%c) [%3d\\%]\",\n\t\"[%2d] Empty\\n\"\n};\n\nvoid print_size(unsigned int devsize) {\n\tif (devsize % (1024 * 1024 * 1024) == 0) {\n\t\t//Gigabytes\n\t\tfprintf(destfile, \"\\tSize: %dGB\", (devsize / 1024 / 1024 / 1024));\n\t} else {\n\t\t//Small MTD, use Megabytes\n\t\tfprintf(destfile, \"\\tSize: %dMB\", (devsize / 1024 / 1024));\n\t}\n}\n\nunsigned int print_minfo(void) {\n\tint i = 0;\n\tstruct m_partition_info *bi = NULL;\n\n\tstruct m_device_info *mtdi = NULL;\n\tmtdi = M_GET_DEV_INFO(0);\n\tfprintf(destfile, \"MTD Name: %s\", mtdi->name);\n\tunsigned int devsize = mtdi->size;\n\tprint_size(devsize);\n\tprintln();\n\n\tprintln();\n\tfprintf(destfile, \"%s\", m_menu_partition_str[0]);\n\tprintln();\n\tprintln();\n\tfprintf(destfile, \"magic : %08x\", m_partinfo.magic);\n\tprintln();\n\tprintln();\n\tfprintf(destfile, m_menu_partition_str[2], m_partinfo.cur_epk_ver);\n\tprintln();\n\tfprintf(destfile, m_menu_partition_str[3], m_partinfo.old_epk_ver);\n\tprintln();\n\tprintln();\n\tfor (i = 0; i < (m_partinfo.npartition); i++) {\n\t\tbi = M_GET_PART_INFO(i);\n\n\t\tfprintf(destfile, m_menu_partition_info[0], i, bi->name, bi->offset, (bi->offset + bi->size), bi->size);\n\n\t\tfprintf(destfile, m_menu_partition_info[1], (bi->mask_flags & PART_FLG_FIXED) ? 'F' : '-', (bi->mask_flags & PART_FLG_MASTER) ? 'M' : '-', (bi->mask_flags & PART_FLG_IDKEY) ? 'I' : '-', (bi->mask_flags & PART_FLG_CACHE) ? 'C' : '-');\n\n\t\tif (strlen(bi->filename)) {\n\t\t\tfprintf(destfile, m_menu_partition_info[2], bi->filename, bi->filesize, bi->sw_ver, bi->used ? 'U' : 'u', bi->valid ? 'V' : 'v');\n\t\t\tprintln();\n\t\t} else\n\t\t\tprintln();\n\t}\n\n\treturn 0;\n}\n\nunsigned int print_p1info(void) {\n\tint i = 0;\n\tstruct p1_partition_info *p1i = NULL;\n\n\tstruct p1_device_info *p1di = NULL;\n\tp1di = P1_GET_DEV_INFO();\n\tfprintf(destfile, \"Flash Name: %s\", p1di->name);\n\tunsigned int devsize = p1di->size;\n\tprint_size(devsize);\n\tprintln();\n\n\tprintln();\n\tfprintf(destfile, \"%s\", p_menu_partition_str[0]);\n\tprintln();\n\tprintln();\n\tfprintf(destfile, \"magic : %08x\", p1_partinfo.magic);\n\tprintln();\n\tprintln();\n\tfprintf(destfile, p_menu_partition_str[2], p1_partinfo.cur_epk_ver);\n\tprintln();\n\tfprintf(destfile, p_menu_partition_str[3], p1_partinfo.old_epk_ver);\n\tprintln();\n\tprintln();\n\n\tif (p1_partinfo.npartition > PM_PARTITION_MAX) {\n\t\tprintf(\"[ERROR] Number of partition is %d\\n\", p1_partinfo.npartition);\n\t\treturn (unsigned int)-1;\n\t}\n\n\tfor (i = 0; i < (p1_partinfo.npartition); i++) {\n\t\tp1i = P1_GET_PART_INFO(i);\n\n\t\tfprintf(destfile, p1_menu_partition_info[0], i, p1i->name, p1i->offset, (p1i->offset + p1i->size), p1i->size);\n\n\t\tfprintf(destfile, p1_menu_partition_info[1], (p1i->mask_flags & PART_FLG_FIXED) ? 'F' : '-', (p1i->mask_flags & PART_FLG_MASTER) ? 'M' : '-', (p1i->mask_flags & PART_FLG_SECURED) ? 'S' : '-', (p1i->mask_flags & PART_FLG_IDKEY) ? 'I' : '-', (p1i->mask_flags & PART_FLG_CACHE) ? 'C' : ((p1i->mask_flags & PART_FLG_DATA) ? 'D' : '-')\n\t\t\t);\n\n\t\tif (p1i->mask_flags & PART_FLG_ERASE)\n\t\t\tfprintf(destfile, \"*\");\n\n\t\tif (strlen(p1i->filename)) {\n\t\t\tfprintf(destfile, p1_menu_partition_info[2], p1i->filename, p1i->filesize, p1i->sw_ver, p1i->used ? 'U' : 'u', p1i->valid ? 'V' : 'v');\n\t\t\tprintln();\n\t\t} else\n\t\t\tprintln();\n\t}\n\n\treturn 0;\n}\n\nunsigned int print_p2info(void) {\n\tint i = 0;\n\tstruct p2_partition_info *p2i = NULL;\n\n\tstruct p2_device_info *p2di = NULL;\n\tp2di = P2_GET_DEV_INFO();\n\tfprintf(destfile, \"Flash Name: %s\", p2di->name);\n\tunsigned int devsize = p2di->size;\n\tprint_size(devsize);\n\tprintln();\n\n\tprintln();\n\tfprintf(destfile, \"%s\", p_menu_partition_str[0]);\n\tprintln();\n\tprintln();\n\tfprintf(destfile, \"magic : %08x\", p2_partinfo.magic);\n\tprintln();\n\tprintln();\n\tfprintf(destfile, p_menu_partition_str[2], p2_partinfo.cur_epk_ver);\n\tprintln();\n\tfprintf(destfile, p_menu_partition_str[3], p2_partinfo.old_epk_ver);\n\tprintln();\n\tprintln();\n\n\tif (p2_partinfo.npartition > P2_PARTITION_MAX) {\n\t\tprintf(\"[ERROR] Number of partition is %d\\n\", p2_partinfo.npartition);\n\t\treturn (unsigned int)-1;\n\t}\n\n\tfor (i = 0; i < (p2_partinfo.npartition); i++) {\n\t\tp2i = P2_GET_PART_INFO(i);\n\n\t\tfprintf(destfile, p2_menu_partition_info[0], i, p2i->name, U64_UPPER(p2i->offset), U64_LOWER(p2i->offset), U64_UPPER(p2i->offset + p2i->size), U64_LOWER(p2i->offset + p2i->size), U64_UPPER(p2i->size), U64_LOWER(p2i->size));\n\n\t\tfprintf(destfile, p2_menu_partition_info[1], (p2i->mask_flags & PART_FLG_FIXED) ? 'F' : '-', (p2i->mask_flags & PART_FLG_MASTER) ? 'M' : '-', (p2i->mask_flags & PART_FLG_SECURED) ? 'S' : '-', (p2i->mask_flags & PART_FLG_IDKEY) ? 'I' : '-', (p2i->mask_flags & PART_FLG_CACHE) ? 'C' : ((p2i->mask_flags & PART_FLG_DATA) ? 'D' : '-')\n\t\t\t);\n\n\t\tif (p2i->mask_flags & PART_FLG_ERASE)\n\t\t\tfprintf(destfile, \"*\");\n\n\t\tif (strlen(p2i->filename)) {\n\t\t\tfprintf(destfile, p2_menu_partition_info[2], p2i->filename, p2i->filesize, p2i->sw_ver, p2i->used ? 'U' : 'u', p2i->valid ? 'V' : 'v', (unsigned long)((double)p2i->filesize / p2i->size * 100));\n\t\t\tprintln();\n\t\t} else\n\t\t\tprintln();\n\t}\n\n\treturn 0;\n}\n\nunsigned int do_partinfo(void) {\n\tfprintf(destfile, \"%s Detected\", modelname);\n\tprintln();\n\tprintln();\n\n\tswitch (part_type) {\n\tcase STRUCT_PARTINFOv2:\n\t\tprint_p2info();\n\t\tbreak;\n\tcase STRUCT_PARTINFOv1:\n\t\tprint_p1info();\n\t\tbreak;\n\tcase STRUCT_MTDINFO:\n\t\tprint_minfo();\n\t\tbreak;\n\tdefault:\n\t\terr_exit(\"Unhandled partition table structure\\n\");\n\t\tbreak;\n\t}\n\tprintln();\n\n\tchar buf[256];\n\trewind(destfile);\n\tprintf(\"\\n\");\n\twhile (fgets(buf, sizeof buf, destfile)) {\t//print file we just wrote to stdout\n\t\tprintf(\"%s\", buf);\n\t}\n\tfclose(destfile);\n\treturn 0;\n}\n\nunsigned int load_partinfo(const char *filename) {\n\tFILE *file;\n\tfile = fopen(filename, \"rb\");\n\tif (file == NULL) {\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\t}\n\n\tsize_t size = 0;\n\n\tswitch (part_type) {\n\tcase STRUCT_PARTINFOv2:\n\t\tsize = sizeof(struct p2_partmap_info);\n\t\tfread(&p2_partinfo, 1, size, file);\n\t\tbreak;\n\tcase STRUCT_PARTINFOv1:\n\t\tsize = sizeof(struct p1_partmap_info);\n\t\tfread(&p1_partinfo, 1, size, file);\n\t\tbreak;\n\tcase STRUCT_MTDINFO:\n\t\tsize = sizeof(struct m_partmap_info);\n\t\tfread(&m_partinfo, 1, size, file);\n\t\tbreak;\n\tdefault:\n\t\tfclose(file);\n\t\terr_exit(\"Unhandled partition table structure\\n\");\n\t\tbreak;\n\t}\n\treturn 0;\n}\n\nunsigned int dump_partinfo(const char *filename, const char *outfile) {\n\tdestfile = fopen(outfile, \"w+\");\n\tif (destfile == NULL)\n\t\terr_exit(\"Can't open file %s for writing. Error is: %s\\n\", outfile, strerror(errno));\n\n\tload_partinfo(filename);\n\tdo_partinfo();\n\treturn 0;\n}\n"
  },
  {
    "path": "src/philips.c",
    "content": "/**\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"config.h\"\n#include \"mfile.h\"\n#include \"util.h\"\n#include \"philips.h\"\n#include \"main.h\"\n\n#define PHILIPS_DEBUG\n\nMFILE *is_philips_fusion1(const char *filename){\n\t\tMFILE *mf = mopen(filename, O_RDONLY);\n\t\tif(!mf){\n\t\t\terr_exit(\"mfopen failed for %s\\n\", filename);\n\t\t}\n\t\tuint8_t *data = mdata(mf, uint8_t);\n\t\tif(!memcmp(data, PHILIPS_FUSION1_MAGIC, strlen(PHILIPS_FUSION1_MAGIC))){\n\t\t\treturn mf;\n\t\t}\n\t\tmclose(mf);\n\t\treturn NULL;\n}\n\nvoid extract_philips_fusion1(MFILE *mf, config_opts_t *config_opts){\n\tchar *basename = my_basename(mf->path);\n\tchar *name = remove_ext(basename);\n\tasprintf_inplace(&config_opts->dest_dir, \"%s/%s\", config_opts->dest_dir, name);\n\tcreateFolder(config_opts->dest_dir);\n\n\tuint8_t *data = mdata(mf, uint8_t);\n\tstruct philips_fusion1_upg *upg = mdata(mf, struct philips_fusion1_upg);\n\tstruct philips_fusion1_part *part_table = (struct philips_fusion1_part *)&data[0xB0];\n\n\tprintf(\"Fusion1 firmware contains %u partitions (first at 0x%08X)\\n\",\n\t\tupg->numPartitions, upg->firstPartition\n\t);\n\n\tuint i;\n\tfor(i=0; i<upg->numPartitions; i++){\n\t\tstruct philips_fusion1_part *part = &part_table[i];\n\t\tprintf(\"[Part %u] Index: %02u - 0x%08X (0x%08X bytes)\\n\",\n\t\t\ti, part->index, part->offset, part->size\n\t\t);\n\n\t\t#ifdef PHILIPS_DEBUG\n\t\tprintf(\"UNK0: 0x%08X\\n\", part->unk0);\n\t\tprintf(\"UNK1: 0x%08X\\n\", part->unk1);\n\t\tprintf(\"UNK2: 0x%08X\\n\", part->unk2);\n\t\tprintf(\"UNK3: 0x%08X\\n\\n\", part->unk3);\n\t\t#endif\n\n\t\tchar *path;\n\t\tasprintf(&path, \"%s/part_%d.pak\", config_opts->dest_dir, i);\n\t\tprintf(\"  Writing partition to %s\\n\", path);\n\n\t\tMFILE *out = mfopen(path, \"w+\");\n\t\tif(out) {\n\t\t\tmfile_map(out, part->size);\n\t\t\tmemcpy(\n\t\t\t\tmdata(out, void),\n\t\t\t\t&data[part->offset],\n\t\t\t\tpart->size\n\t\t\t);\n\t\t\tmclose(out);\n\n\t\t\thandle_file(path, config_opts);\n\t\t} else {\n\t\t\tprintf(\"A package wasn't written to disk because of a memory allocation failure\\n\");\n\t\t}\n\n\t\tfree(path);\n\t}\n\n\tfree(name);\n\tfree(basename);\n}\n"
  },
  {
    "path": "src/realtek.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <errno.h>\n\n#include \"mfile.h\"\n#include \"realtek/rtsplit.h\"\n#include \"util.h\"\n\nMFILE *is_rtk_bspfw(const char *filename){\n\tMFILE *mf = mopen(filename, O_RDONLY);\n\tif(mf == NULL){\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\t}\n\n\tkernel_image_header *hdr = mdata(mf, kernel_image_header);\n\n\tint zero_size = member_size(kernel_image_header, reserved);\n\tuint8_t reserved[zero_size];\n\tmemset(&reserved, 0x00, zero_size);\n\n\tint matches = 0;\n\n\tfor(; moff(mf, hdr) < msize(mf); hdr++){\n\t\tint stop = 0;\n\t\tswitch(hdr->magic){\n\t\t\tcase HEADER_AUDIO1_IMAGE:\n\t\t\tcase HEADER_AUDIO2_IMAGE:\n\t\t\tcase HEADER_VIDEO1_IMAGE:\n\t\t\tcase HEADER_VIDEO2_IMAGE:\n\t\t\t\tif(memcmp(&hdr->reserved, &reserved, zero_size) != 0){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif(hdr->offset > msize(mf) || (hdr->offset + hdr->size) > msize(mf)){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tmatches++;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tstop = 1;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif(stop){\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(matches < 1){\n\t\tmclose(mf);\n\t\treturn NULL;\n\t}\n\n\treturn mf;\n}\n\nvoid split_rtk_bspfw(MFILE *mf, const char *destdir) {\n\tchar *innerDirectory;\n\tasprintf(&innerDirectory, \"%s/bspfw.pak.split\", destdir);\n\tcreateFolder(innerDirectory);\n\n\tkernel_image_header *hdr = mdata(mf, kernel_image_header);\n\tfor(; moff(mf, hdr) < msize(mf); hdr++){\n\t\tchar *filepath = NULL;\n\n\t\tswitch(hdr->magic){\n\t\t\tcase HEADER_AUDIO1_IMAGE:\n\t\t\tcase HEADER_AUDIO2_IMAGE:\n\t\t\tcase HEADER_VIDEO1_IMAGE:\n\t\t\tcase HEADER_VIDEO2_IMAGE: {\n\t\t\t\tchar *filename = (hdr->magic == HEADER_AUDIO1_IMAGE) ? \"ACPU1\" : (\n\t\t\t\t\t(hdr->magic == HEADER_AUDIO2_IMAGE) ? \"ACPU2\" : (\n\t\t\t\t\t\t(hdr->magic == HEADER_VIDEO1_IMAGE) ? \"VCPU1\" : \"VCPU2\"\n\t\t\t\t\t)\n\t\t\t\t);\n\n\t\t\t\tprintf(\"Found %s firmware (offset='0x%x', size='0x%x')\\n\", filename, hdr->offset, hdr->size);\n\n\t\t\t\tasprintf(&filepath, \"%s/%s.bin\", innerDirectory, filename);\n\t\t\t\tprintf(\" == Saving to %s\\n\", filepath);\n\n\t\t\t\tMFILE *out = mfopen(filepath, \"w+\");\n\t\t\t\tif(out == NULL){\n\t\t\t\t\terr_exit(\"Cannot open '%s' for writing\\n\", filepath);\n\t\t\t\t}\n\n\t\t\t\tmfile_map(out, hdr->size);\n\t\t\t\tmemcpy(\n\t\t\t\t\tmdata(out, void),\n\t\t\t\t\tmdata(mf, uint8_t) + hdr->offset,\n\t\t\t\t\thdr->size\n\t\t\t\t);\n\t\t\t\tmclose(out);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(filepath != NULL){\n\t\t\tfree(filepath);\n\t\t}\n\t}\n\tfree(innerDirectory);\n}\n"
  },
  {
    "path": "src/squashfs/CMakeLists.txt",
    "content": "add_library(squashfs compressor.c gzip_wrapper.c lzo_wrapper.c swap.c read_xattrs.c unsquash-1.c unsquash-2.c unsquash-3.c unsquash-4.c unsquashfs.c unsquashfs_info.c unsquashfs_xattr.c)\ntarget_include_directories(squashfs PUBLIC\n\t${INC}/squashfs\n\t${LZO_INCLUDE_DIR}\n)\ntarget_compile_definitions(squashfs PRIVATE\n\t-DGZIP_SUPPORT\n\t-DLZO_SUPPORT\n\t-DCOMP_DEFAULT=\\\"gzip\\\"\n\t-DXATTR_SUPPORT\n\t-DXATTR_DEFAULT\n)"
  },
  {
    "path": "src/squashfs/action.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2011, 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * action.c\n */\n\n#include <fcntl.h>\n#include <dirent.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <fnmatch.h>\n#include <pwd.h>\n#include <grp.h>\n#include <sys/wait.h>\n#include <regex.h>\n#include <limits.h>\n#include <errno.h>\n\n#include \"squashfs_fs.h\"\n#include \"mksquashfs.h\"\n#include \"action.h\"\n#include \"error.h\"\n\n/*\n * code to parse actions\n */\n\nstatic char *cur_ptr, *source;\nstatic struct action *fragment_spec = NULL;\nstatic struct action *exclude_spec = NULL;\nstatic struct action *empty_spec = NULL;\nstatic struct action *move_spec = NULL;\nstatic struct action *other_spec = NULL;\nstatic int fragment_count = 0;\nstatic int exclude_count = 0;\nstatic int empty_count = 0;\nstatic int move_count = 0;\nstatic int other_count = 0;\n\nstatic struct file_buffer *def_fragment = NULL;\n\nstatic struct token_entry token_table[] = {\n\t{\"(\", TOK_OPEN_BRACKET, 1,},\n\t{\")\", TOK_CLOSE_BRACKET, 1},\n\t{\"&&\", TOK_AND, 2},\n\t{\"||\", TOK_OR, 2},\n\t{\"!\", TOK_NOT, 1},\n\t{\",\", TOK_COMMA, 1},\n\t{\"@\", TOK_AT, 1},\n\t{\" \", TOK_WHITE_SPACE, 1},\n\t{\"\\t \", TOK_WHITE_SPACE, 1},\n\t{\"\", -1, 0}\n};\n\nstatic struct test_entry test_table[];\n\nstatic struct action_entry action_table[];\n\nstatic struct expr *parse_expr(int subexp);\n\nextern char *pathname(struct dir_ent *);\n\nextern char *subpathname(struct dir_ent *);\n\nextern int read_file(char *filename, char *type, int (parse_line) (char *));\n\n/*\n * Lexical analyser\n */\n#define STR_SIZE 256\n\nstatic int get_token(char **string) {\n\t/* string buffer */\n\tstatic char *str = NULL;\n\tstatic int size = 0;\n\n\tchar *str_ptr;\n\tint cur_size, i, quoted;\n\n\twhile (1) {\n\t\tif (*cur_ptr == '\\0')\n\t\t\treturn TOK_EOF;\n\t\tfor (i = 0; token_table[i].token != -1; i++)\n\t\t\tif (strncmp(cur_ptr, token_table[i].string, token_table[i].size) == 0)\n\t\t\t\tbreak;\n\t\tif (token_table[i].token != TOK_WHITE_SPACE)\n\t\t\tbreak;\n\t\tcur_ptr++;\n\t}\n\n\tif (token_table[i].token != -1) {\n\t\tcur_ptr += token_table[i].size;\n\t\treturn token_table[i].token;\n\t}\n\n\t/* string */\n\tif (str == NULL) {\n\t\tstr = malloc(STR_SIZE);\n\t\tif (str == NULL)\n\t\t\tMEM_ERROR();\n\t\tsize = STR_SIZE;\n\t}\n\n\t/* Initialise string being read */\n\tstr_ptr = str;\n\tcur_size = 0;\n\tquoted = 0;\n\n\twhile (1) {\n\t\twhile (*cur_ptr == '\"') {\n\t\t\tcur_ptr++;\n\t\t\tquoted = !quoted;\n\t\t}\n\n\t\tif (*cur_ptr == '\\0') {\n\t\t\t/* inside quoted string EOF, otherwise end of string */\n\t\t\tif (quoted)\n\t\t\t\treturn TOK_EOF;\n\t\t\telse\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (!quoted) {\n\t\t\tfor (i = 0; token_table[i].token != -1; i++)\n\t\t\t\tif (strncmp(cur_ptr, token_table[i].string, token_table[i].size) == 0)\n\t\t\t\t\tbreak;\n\t\t\tif (token_table[i].token != -1)\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (*cur_ptr == '\\\\') {\n\t\t\tcur_ptr++;\n\t\t\tif (*cur_ptr == '\\0')\n\t\t\t\treturn TOK_EOF;\n\t\t}\n\n\t\tif (cur_size + 2 > size) {\n\t\t\tchar *tmp;\n\n\t\t\tsize = (cur_size + 1 + STR_SIZE) & ~(STR_SIZE - 1);\n\n\t\t\ttmp = realloc(str, size);\n\t\t\tif (tmp == NULL)\n\t\t\t\tMEM_ERROR();\n\n\t\t\tstr_ptr = str_ptr - str + tmp;\n\t\t\tstr = tmp;\n\t\t}\n\n\t\t*str_ptr++ = *cur_ptr++;\n\t\tcur_size++;\n\t}\n\n\t*str_ptr = '\\0';\n\t*string = str;\n\treturn TOK_STRING;\n}\n\nstatic int peek_token(char **string) {\n\tchar *saved = cur_ptr;\n\tint token = get_token(string);\n\n\tcur_ptr = saved;\n\n\treturn token;\n}\n\n/*\n * Expression parser\n */\nstatic void free_parse_tree(struct expr *expr) {\n\tif (expr->type == ATOM_TYPE) {\n\t\tint i;\n\n\t\tfor (i = 0; i < expr->atom.test->args; i++)\n\t\t\tfree(expr->atom.argv[i]);\n\n\t\tfree(expr->atom.argv);\n\t} else if (expr->type == UNARY_TYPE)\n\t\tfree_parse_tree(expr->unary_op.expr);\n\telse {\n\t\tfree_parse_tree(expr->expr_op.lhs);\n\t\tfree_parse_tree(expr->expr_op.rhs);\n\t}\n\n\tfree(expr);\n}\n\nstatic struct expr *create_expr(struct expr *lhs, int op, struct expr *rhs) {\n\tstruct expr *expr;\n\n\tif (rhs == NULL) {\n\t\tfree_parse_tree(lhs);\n\t\treturn NULL;\n\t}\n\n\texpr = malloc(sizeof(*expr));\n\tif (expr == NULL)\n\t\tMEM_ERROR();\n\n\texpr->type = OP_TYPE;\n\texpr->expr_op.lhs = lhs;\n\texpr->expr_op.rhs = rhs;\n\texpr->expr_op.op = op;\n\n\treturn expr;\n}\n\nstatic struct expr *create_unary_op(struct expr *lhs, int op) {\n\tstruct expr *expr;\n\n\tif (lhs == NULL)\n\t\treturn NULL;\n\n\texpr = malloc(sizeof(*expr));\n\tif (expr == NULL)\n\t\tMEM_ERROR();\n\n\texpr->type = UNARY_TYPE;\n\texpr->unary_op.expr = lhs;\n\texpr->unary_op.op = op;\n\n\treturn expr;\n}\n\nstatic struct expr *parse_test(char *name) {\n\tchar *string;\n\tint token;\n\tint i;\n\tstruct test_entry *test;\n\tstruct expr *expr;\n\n\tfor (i = 0; test_table[i].args != -1; i++)\n\t\tif (strcmp(name, test_table[i].name) == 0)\n\t\t\tbreak;\n\n\tif (test_table[i].args == -1) {\n\t\tSYNTAX_ERROR(\"Non-existent test \\\"%s\\\"\\n\", name);\n\t\treturn NULL;\n\t}\n\n\ttest = &test_table[i];\n\n\texpr = malloc(sizeof(*expr));\n\tif (expr == NULL)\n\t\tMEM_ERROR();\n\n\texpr->type = ATOM_TYPE;\n\n\texpr->atom.argv = malloc(test->args * sizeof(char *));\n\tif (expr->atom.argv == NULL)\n\t\tMEM_ERROR();\n\n\texpr->atom.test = test;\n\texpr->atom.data = NULL;\n\n\t/*\n\t * If the test has no arguments, allow it to be typed\n\t *  without brackets\n\t */\n\tif (test->args == 0) {\n\t\ttoken = peek_token(&string);\n\n\t\tif (token != TOK_OPEN_BRACKET)\n\t\t\tgoto skip_args;\n\t}\n\n\ttoken = get_token(&string);\n\n\tif (token != TOK_OPEN_BRACKET) {\n\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected \\\"(\\\"\\n\", TOK_TO_STR(token, string));\n\t\tgoto failed;\n\t}\n\n\tfor (i = 0; i < test->args; i++) {\n\t\ttoken = get_token(&string);\n\n\t\tif (token != TOK_STRING) {\n\t\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected \" \"argument\\n\", TOK_TO_STR(token, string));\n\t\t\tgoto failed;\n\t\t}\n\n\t\texpr->atom.argv[i] = strdup(string);\n\n\t\tif (i + 1 < test->args) {\n\t\t\ttoken = get_token(&string);\n\n\t\t\tif (token != TOK_COMMA) {\n\t\t\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", \" \"expected \\\",\\\"\\n\", TOK_TO_STR(token, string));\n\t\t\t\tgoto failed;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (test->parse_args) {\n\t\tint res = test->parse_args(test, &expr->atom);\n\n\t\tif (res == 0)\n\t\t\tgoto failed;\n\t}\n\n\ttoken = get_token(&string);\n\n\tif (token != TOK_CLOSE_BRACKET) {\n\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected \\\")\\\"\\n\", TOK_TO_STR(token, string));\n\t\tgoto failed;\n\t}\n\n skip_args:\n\treturn expr;\n\n failed:\n\tfree(expr->atom.argv);\n\tfree(expr);\n\treturn NULL;\n}\n\nstatic struct expr *get_atom() {\n\tchar *string;\n\tint token = get_token(&string);\n\n\tswitch (token) {\n\tcase TOK_NOT:\n\t\treturn create_unary_op(get_atom(), token);\n\tcase TOK_OPEN_BRACKET:\n\t\treturn parse_expr(1);\n\tcase TOK_STRING:\n\t\treturn parse_test(string);\n\tdefault:\n\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected test \" \"operation, \\\"!\\\", or \\\"(\\\"\\n\", TOK_TO_STR(token, string));\n\t\treturn NULL;\n\t}\n}\n\nstatic struct expr *parse_expr(int subexp) {\n\tstruct expr *expr = get_atom();\n\n\twhile (expr) {\n\t\tchar *string;\n\t\tint op = get_token(&string);\n\n\t\tif (op == TOK_EOF) {\n\t\t\tif (subexp) {\n\t\t\t\tfree_parse_tree(expr);\n\t\t\t\tSYNTAX_ERROR(\"Expected \\\"&&\\\", \\\"||\\\" or \" \"\\\")\\\", got EOF\\n\");\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tif (op == TOK_CLOSE_BRACKET) {\n\t\t\tif (!subexp) {\n\t\t\t\tfree_parse_tree(expr);\n\t\t\t\tSYNTAX_ERROR(\"Unexpected \\\")\\\", expected \" \"\\\"&&\\\", \\\"!!\\\" or EOF\\n\");\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tif (op != TOK_AND && op != TOK_OR) {\n\t\t\tfree_parse_tree(expr);\n\t\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected \" \"\\\"&&\\\" or \\\"||\\\"\\n\", TOK_TO_STR(op, string));\n\t\t\treturn NULL;\n\t\t}\n\n\t\texpr = create_expr(expr, op, get_atom());\n\t}\n\n\treturn expr;\n}\n\n/*\n * Action parser\n */\nint parse_action(char *s) {\n\tchar *string, **argv = NULL;\n\tint i, token, args = 0;\n\tstruct expr *expr;\n\tstruct action_entry *action;\n\tvoid *data = NULL;\n\tstruct action **spec_list;\n\tint spec_count;\n\n\tcur_ptr = source = s;\n\ttoken = get_token(&string);\n\n\tif (token != TOK_STRING) {\n\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected name\\n\", TOK_TO_STR(token, string));\n\t\treturn 0;\n\t}\n\n\tfor (i = 0; action_table[i].args != -1; i++)\n\t\tif (strcmp(string, action_table[i].name) == 0)\n\t\t\tbreak;\n\n\tif (action_table[i].args == -1) {\n\t\tSYNTAX_ERROR(\"Non-existent action \\\"%s\\\"\\n\", string);\n\t\treturn 0;\n\t}\n\n\taction = &action_table[i];\n\n\ttoken = get_token(&string);\n\n\tif (token == TOK_AT)\n\t\tgoto skip_args;\n\n\tif (token != TOK_OPEN_BRACKET) {\n\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected \\\"(\\\"\\n\", TOK_TO_STR(token, string));\n\t\tgoto failed;\n\t}\n\n\t/*\n\t * speculatively read all the arguments, and then see if the\n\t * number of arguments read is the number expected, this handles\n\t * actions with a variable number of arguments\n\t */\n\ttoken = get_token(&string);\n\tif (token == TOK_CLOSE_BRACKET)\n\t\tgoto skip_args;\n\n\twhile (1) {\n\t\tif (token != TOK_STRING) {\n\t\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected \" \"argument\\n\", TOK_TO_STR(token, string));\n\t\t\tgoto failed;\n\t\t}\n\n\t\targv = realloc(argv, (args + 1) * sizeof(char *));\n\t\tif (argv == NULL)\n\t\t\tMEM_ERROR();\n\n\t\targv[args++] = strdup(string);\n\n\t\ttoken = get_token(&string);\n\n\t\tif (token == TOK_CLOSE_BRACKET)\n\t\t\tbreak;\n\n\t\tif (token != TOK_COMMA) {\n\t\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected \" \"\\\",\\\" or \\\")\\\"\\n\", TOK_TO_STR(token, string));\n\t\t\tgoto failed;\n\t\t}\n\t\ttoken = get_token(&string);\n\t}\n\n skip_args:\n\t/*\n\t * expected number of arguments?\n\t */\n\tif (action->args != -2 && args != action->args) {\n\t\tSYNTAX_ERROR(\"Unexpected number of arguments, expected %d, \" \"got %d\\n\", action->args, args);\n\t\tgoto failed;\n\t}\n\n\tif (action->parse_args) {\n\t\tint res = action->parse_args(action, args, argv, &data);\n\n\t\tif (res == 0)\n\t\t\tgoto failed;\n\t}\n\n\tif (token == TOK_CLOSE_BRACKET)\n\t\ttoken = get_token(&string);\n\n\tif (token != TOK_AT) {\n\t\tSYNTAX_ERROR(\"Unexpected token \\\"%s\\\", expected \\\"@\\\"\\n\", TOK_TO_STR(token, string));\n\t\tgoto failed;\n\t}\n\n\texpr = parse_expr(0);\n\n\tif (expr == NULL)\n\t\tgoto failed;\n\n\t/*\n\t * choose action list and increment action counter\n\t */\n\tswitch (action->type) {\n\tcase FRAGMENT_ACTION:\n\t\tspec_count = fragment_count++;\n\t\tspec_list = &fragment_spec;\n\t\tbreak;\n\tcase EXCLUDE_ACTION:\n\t\tspec_count = exclude_count++;\n\t\tspec_list = &exclude_spec;\n\t\tbreak;\n\tcase EMPTY_ACTION:\n\t\tspec_count = empty_count++;\n\t\tspec_list = &empty_spec;\n\t\tbreak;\n\tcase MOVE_ACTION:\n\t\tspec_count = move_count++;\n\t\tspec_list = &move_spec;\n\t\tbreak;\n\tdefault:\n\t\tspec_count = other_count++;\n\t\tspec_list = &other_spec;\n\t}\n\n\t*spec_list = realloc(*spec_list, (spec_count + 1) * sizeof(struct action));\n\tif (*spec_list == NULL)\n\t\tMEM_ERROR();\n\n\t(*spec_list)[spec_count].type = action->type;\n\t(*spec_list)[spec_count].action = action;\n\t(*spec_list)[spec_count].args = args;\n\t(*spec_list)[spec_count].argv = argv;\n\t(*spec_list)[spec_count].expr = expr;\n\t(*spec_list)[spec_count].data = data;\n\n\treturn 1;\n\n failed:\n\tfree(argv);\n\treturn 0;\n}\n\n/*\n * Evaluate expressions\n */\nstatic int eval_expr(struct expr *expr, struct action_data *action_data) {\n\tint match;\n\n\tswitch (expr->type) {\n\tcase ATOM_TYPE:\n\t\tmatch = expr->atom.test->fn(&expr->atom, action_data);\n\t\tbreak;\n\tcase UNARY_TYPE:\n\t\tmatch = !eval_expr(expr->unary_op.expr, action_data);\n\t\tbreak;\n\tdefault:\n\t\tmatch = eval_expr(expr->expr_op.lhs, action_data);\n\n\t\tif ((expr->expr_op.op == TOK_AND && match) || (expr->expr_op.op == TOK_OR && !match))\n\t\t\tmatch = eval_expr(expr->expr_op.rhs, action_data);\n\t\tbreak;\n\t}\n\n\treturn match;\n}\n\n/*\n * Read action file, passing each line to parse_action() for\n * parsing.\n *\n * One action per line, of the form\n *\taction(arg1,arg2)@expr(arg1,arg2)....\n *\n * Actions can be split across multiple lines using \"\\\".\n *\n * Blank lines and comment lines indicated by # are supported.\n */\nint read_action_file(char *filename) {\n\treturn read_file(filename, \"action\", parse_action);\n}\n\n/*\n * General action evaluation code\n */\nint actions() {\n\treturn other_count;\n}\n\nvoid eval_actions(struct dir_ent *dir_ent) {\n\tint i, match;\n\tstruct action_data action_data;\n\tint file_type = dir_ent->inode->buf.st_mode & S_IFMT;\n\n\taction_data.name = dir_ent->name;\n\taction_data.pathname = pathname(dir_ent);\n\taction_data.subpath = subpathname(dir_ent);\n\taction_data.buf = &dir_ent->inode->buf;\n\taction_data.depth = dir_ent->our_dir->depth;\n\n\tfor (i = 0; i < other_count; i++) {\n\t\tstruct action *action = &other_spec[i];\n\n\t\tif ((action->action->file_types & file_type) == 0)\n\t\t\t/* action does not operate on this file type */\n\t\t\tcontinue;\n\n\t\tmatch = eval_expr(action->expr, &action_data);\n\n\t\tif (match)\n\t\t\taction->action->run_action(action, dir_ent);\n\t}\n}\n\n/*\n * Fragment specific action code\n */\nvoid *eval_frag_actions(struct dir_ent *dir_ent) {\n\tint i, match;\n\tstruct action_data action_data;\n\n\taction_data.name = dir_ent->name;\n\taction_data.pathname = pathname(dir_ent);\n\taction_data.subpath = subpathname(dir_ent);\n\taction_data.buf = &dir_ent->inode->buf;\n\taction_data.depth = dir_ent->our_dir->depth;\n\n\tfor (i = 0; i < fragment_count; i++) {\n\t\tmatch = eval_expr(fragment_spec[i].expr, &action_data);\n\t\tif (match)\n\t\t\treturn &fragment_spec[i].data;\n\t}\n\n\treturn &def_fragment;\n}\n\nvoid *get_frag_action(void *fragment) {\n\tstruct action *spec_list_end = &fragment_spec[fragment_count];\n\tstruct action *action;\n\n\tif (fragment == NULL)\n\t\treturn &def_fragment;\n\n\tif (fragment_count == 0)\n\t\treturn NULL;\n\n\tif (fragment == &def_fragment)\n\t\taction = &fragment_spec[0] - 1;\n\telse\n\t\taction = fragment - offsetof(struct action, data);\n\n\tif (++action == spec_list_end)\n\t\treturn NULL;\n\n\treturn &action->data;\n}\n\n/*\n * Exclude specific action code\n */\nint exclude_actions() {\n\treturn exclude_count;\n}\n\nint eval_exclude_actions(char *name, char *pathname, char *subpath, struct stat *buf, int depth) {\n\tint i, match = 0;\n\tstruct action_data action_data;\n\n\taction_data.name = name;\n\taction_data.pathname = pathname;\n\taction_data.subpath = subpath;\n\taction_data.buf = buf;\n\taction_data.depth = depth;\n\n\tfor (i = 0; i < exclude_count && !match; i++)\n\t\tmatch = eval_expr(exclude_spec[i].expr, &action_data);\n\n\treturn match;\n}\n\n/*\n * Fragment specific action code\n */\nstatic void frag_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct inode_info *inode = dir_ent->inode;\n\n\tinode->no_fragments = 0;\n}\n\nstatic void no_frag_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct inode_info *inode = dir_ent->inode;\n\n\tinode->no_fragments = 1;\n}\n\nstatic void always_frag_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct inode_info *inode = dir_ent->inode;\n\n\tinode->always_use_fragments = 1;\n}\n\nstatic void no_always_frag_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct inode_info *inode = dir_ent->inode;\n\n\tinode->always_use_fragments = 0;\n}\n\n/*\n * Compression specific action code\n */\nstatic void comp_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct inode_info *inode = dir_ent->inode;\n\n\tinode->noD = inode->noF = 0;\n}\n\nstatic void uncomp_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct inode_info *inode = dir_ent->inode;\n\n\tinode->noD = inode->noF = 1;\n}\n\n/*\n * Uid/gid specific action code\n */\nstatic long long parse_uid(char *arg) {\n\tchar *b;\n\tlong long uid = strtoll(arg, &b, 10);\n\n\tif (*b == '\\0') {\n\t\tif (uid < 0 || uid >= (1LL << 32)) {\n\t\t\tSYNTAX_ERROR(\"action: uid out of range\\n\");\n\t\t\treturn -1;\n\t\t}\n\t} else {\n\t\tstruct passwd *passwd = getpwnam(arg);\n\n\t\tif (passwd)\n\t\t\tuid = passwd->pw_uid;\n\t\telse {\n\t\t\tSYNTAX_ERROR(\"action: invalid uid or unknown user\\n\");\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\treturn uid;\n}\n\nstatic long long parse_gid(char *arg) {\n\tchar *b;\n\tlong long gid = strtoll(arg, &b, 10);\n\n\tif (*b == '\\0') {\n\t\tif (gid < 0 || gid >= (1LL << 32)) {\n\t\t\tSYNTAX_ERROR(\"action: gid out of range\\n\");\n\t\t\treturn -1;\n\t\t}\n\t} else {\n\t\tstruct group *group = getgrnam(arg);\n\n\t\tif (group)\n\t\t\tgid = group->gr_gid;\n\t\telse {\n\t\t\tSYNTAX_ERROR(\"action: invalid gid or unknown user\\n\");\n\t\t\treturn -1;\n\t\t}\n\t}\n\n\treturn gid;\n}\n\nstatic int parse_uid_args(struct action_entry *action, int args, char **argv, void **data) {\n\tlong long uid;\n\tstruct uid_info *uid_info;\n\n\tuid = parse_uid(argv[0]);\n\tif (uid == -1)\n\t\treturn 0;\n\n\tuid_info = malloc(sizeof(struct uid_info));\n\tif (uid_info == NULL)\n\t\tMEM_ERROR();\n\n\tuid_info->uid = uid;\n\t*data = uid_info;\n\n\treturn 1;\n}\n\nstatic int parse_gid_args(struct action_entry *action, int args, char **argv, void **data) {\n\tlong long gid;\n\tstruct gid_info *gid_info;\n\n\tgid = parse_gid(argv[0]);\n\tif (gid == -1)\n\t\treturn 0;\n\n\tgid_info = malloc(sizeof(struct gid_info));\n\tif (gid_info == NULL)\n\t\tMEM_ERROR();\n\n\tgid_info->gid = gid;\n\t*data = gid_info;\n\n\treturn 1;\n}\n\nstatic int parse_guid_args(struct action_entry *action, int args, char **argv, void **data) {\n\tlong long uid, gid;\n\tstruct guid_info *guid_info;\n\n\tuid = parse_uid(argv[0]);\n\tif (uid == -1)\n\t\treturn 0;\n\n\tgid = parse_gid(argv[1]);\n\tif (gid == -1)\n\t\treturn 0;\n\n\tguid_info = malloc(sizeof(struct guid_info));\n\tif (guid_info == NULL)\n\t\tMEM_ERROR();\n\n\tguid_info->uid = uid;\n\tguid_info->gid = gid;\n\t*data = guid_info;\n\n\treturn 1;\n}\n\nstatic void uid_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct inode_info *inode = dir_ent->inode;\n\tstruct uid_info *uid_info = action->data;\n\n\tinode->buf.st_uid = uid_info->uid;\n}\n\nstatic void gid_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct inode_info *inode = dir_ent->inode;\n\tstruct gid_info *gid_info = action->data;\n\n\tinode->buf.st_gid = gid_info->gid;\n}\n\nstatic void guid_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct inode_info *inode = dir_ent->inode;\n\tstruct guid_info *guid_info = action->data;\n\n\tinode->buf.st_uid = guid_info->uid;\n\tinode->buf.st_gid = guid_info->gid;\n\n}\n\n/*\n * Mode specific action code\n */\nstatic int parse_octal_mode_args(unsigned int mode, int bytes, int args, char **argv, void **data) {\n\tstruct mode_data *mode_data;\n\n\t/* check there's no trailing junk */\n\tif (argv[0][bytes] != '\\0') {\n\t\tSYNTAX_ERROR(\"Unexpected trailing bytes after octal \" \"mode number\\n\");\n\t\treturn 0;\n\t}\n\n\t/* check there's only one argument */\n\tif (args > 1) {\n\t\tSYNTAX_ERROR(\"Octal mode number is first argument, \" \"expected one argument, got %d\\n\", args);\n\t\treturn 0;\n\t}\n\n\t/*  check mode is within range */\n\tif (mode > 07777) {\n\t\tSYNTAX_ERROR(\"Octal mode %o is out of range\\n\", mode);\n\t\treturn 0;\n\t}\n\n\tmode_data = malloc(sizeof(struct mode_data));\n\tif (mode_data == NULL)\n\t\tMEM_ERROR();\n\n\tmode_data->operation = ACTION_MODE_OCT;\n\tmode_data->mode = mode;\n\tmode_data->next = NULL;\n\t*data = mode_data;\n\n\treturn 1;\n}\n\n/*\n * Parse symbolic mode of format [ugoa]+[+-=]PERMS\n * PERMS = [rwxXst]+ or [ugo]\n */\nstatic struct mode_data *parse_sym_mode_arg(char *arg) {\n\tstruct mode_data *mode_data = malloc(sizeof(*mode_data));\n\tint mode = 0;\n\tint mask = 0;\n\tint op;\n\tchar X = 0;\n\n\tif (mode_data == NULL)\n\t\tMEM_ERROR();\n\n\tif (arg[0] != 'u' && arg[0] != 'g' && arg[0] != 'o' && arg[0] != 'a') {\n\t\t/* no ownership specifiers, default to a */\n\t\tmask = 0777;\n\t\tgoto parse_operation;\n\t}\n\n\t/* parse ownership specifiers */\n\twhile (1) {\n\t\tswitch (*arg) {\n\t\tcase 'u':\n\t\t\tmask |= 04700;\n\t\t\tbreak;\n\t\tcase 'g':\n\t\t\tmask |= 02070;\n\t\t\tbreak;\n\t\tcase 'o':\n\t\t\tmask |= 01007;\n\t\t\tbreak;\n\t\tcase 'a':\n\t\t\tmask = 07777;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tgoto parse_operation;\n\t\t}\n\t\targ++;\n\t}\n\n parse_operation:\n\tswitch (*arg) {\n\tcase '+':\n\t\top = ACTION_MODE_ADD;\n\t\tbreak;\n\tcase '-':\n\t\top = ACTION_MODE_REM;\n\t\tbreak;\n\tcase '=':\n\t\top = ACTION_MODE_SET;\n\t\tbreak;\n\tdefault:\n\t\tSYNTAX_ERROR(\"Action mode: Expected one of '+', '-' or '=', \" \"got '%c'\\n\", *arg);\n\t\tgoto failed;\n\t}\n\n\targ++;\n\n\t/* Parse PERMS */\n\tif (*arg == 'u' || *arg == 'g' || *arg == 'o') {\n\t\t/* PERMS = [ugo] */\n\t\tmode = -*arg;\n\t\tif (*++arg != '\\0') {\n\t\t\tSYNTAX_ERROR(\"Action mode: permission 'u', 'g' or 'o' \" \"has trailing characters\\n\");\n\t\t\tgoto failed;\n\t\t}\n\t} else {\n\t\t/* PERMS = [rwxXst]+ */\n\t\twhile (*arg != '\\0') {\n\t\t\tswitch (*arg) {\n\t\t\tcase 'r':\n\t\t\t\tmode |= 0444;\n\t\t\t\tbreak;\n\t\t\tcase 'w':\n\t\t\t\tmode |= 0222;\n\t\t\t\tbreak;\n\t\t\tcase 'x':\n\t\t\t\tmode |= 0111;\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tmode |= 06000;\n\t\t\t\tbreak;\n\t\t\tcase 't':\n\t\t\t\tmode |= 01000;\n\t\t\t\tbreak;\n\t\t\tcase 'X':\n\t\t\t\tX = 1;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tSYNTAX_ERROR(\"Action mode: unrecognised \" \"permission '%c'\\n\", *arg);\n\t\t\t\tgoto failed;\n\t\t\t}\n\n\t\t\targ++;\n\t\t}\n\t\tmode &= mask;\n\t}\n\n\tmode_data->operation = op;\n\tmode_data->mode = mode;\n\tmode_data->mask = mask;\n\tmode_data->X = X;\n\tmode_data->next = NULL;\n\n\treturn mode_data;\n\n failed:\n\tfree(mode_data);\n\treturn NULL;\n}\n\nstatic int parse_sym_mode_args(struct action_entry *action, int args, char **argv, void **data) {\n\tint i;\n\tstruct mode_data *head = NULL, *cur = NULL;\n\n\tfor (i = 0; i < args; i++) {\n\t\tstruct mode_data *entry = parse_sym_mode_arg(argv[i]);\n\n\t\tif (entry == NULL)\n\t\t\treturn 0;\n\n\t\tif (cur) {\n\t\t\tcur->next = entry;\n\t\t\tcur = entry;\n\t\t} else\n\t\t\thead = cur = entry;\n\t}\n\n\t*data = head;\n\n\treturn 1;\n}\n\nstatic int parse_mode_args(struct action_entry *action, int args, char **argv, void **data) {\n\tint n, bytes;\n\tunsigned int mode;\n\n\tif (args == 0) {\n\t\tSYNTAX_ERROR(\"Mode action expects one or more arguments\\n\");\n\t\treturn 0;\n\t}\n\n\t/* octal mode number? */\n\tn = sscanf(argv[0], \"%o%n\", &mode, &bytes);\n\n\tif (n >= 1)\n\t\treturn parse_octal_mode_args(mode, bytes, args, argv, data);\n\telse\n\t\treturn parse_sym_mode_args(action, args, argv, data);\n}\n\nstatic void mode_action(struct action *action, struct dir_ent *dir_ent) {\n\tstruct stat *buf = &dir_ent->inode->buf;\n\tstruct mode_data *mode_data = action->data;\n\tint mode = 0;\n\n\tfor (; mode_data; mode_data = mode_data->next) {\n\t\tif (mode_data->mode < 0) {\n\t\t\t/* 'u', 'g' or 'o' */\n\t\t\tswitch (-mode_data->mode) {\n\t\t\tcase 'u':\n\t\t\t\tmode = (buf->st_mode >> 6) & 07;\n\t\t\t\tbreak;\n\t\t\tcase 'g':\n\t\t\t\tmode = (buf->st_mode >> 3) & 07;\n\t\t\t\tbreak;\n\t\t\tcase 'o':\n\t\t\t\tmode = buf->st_mode & 07;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmode = ((mode << 6) | (mode << 3) | mode) & mode_data->mask;\n\t\t} else if (mode_data->X && ((buf->st_mode & S_IFMT) == S_IFDIR || (buf->st_mode & 0111)))\n\t\t\t/* X permission, only takes effect if inode is a\n\t\t\t * directory or x is set for some owner */\n\t\t\tmode = mode_data->mode | (0111 & mode_data->mask);\n\t\telse\n\t\t\tmode = mode_data->mode;\n\n\t\tswitch (mode_data->operation) {\n\t\tcase ACTION_MODE_OCT:\n\t\t\tbuf->st_mode = (buf->st_mode & ~S_IFMT) | mode;\n\t\t\tbreak;\n\t\tcase ACTION_MODE_SET:\n\t\t\tbuf->st_mode = (buf->st_mode & ~mode_data->mask) | mode;\n\t\t\tbreak;\n\t\tcase ACTION_MODE_ADD:\n\t\t\tbuf->st_mode |= mode;\n\t\t\tbreak;\n\t\tcase ACTION_MODE_REM:\n\t\t\tbuf->st_mode &= ~mode;\n\t\t}\n\t}\n}\n\n/*\n *  Empty specific action code\n */\nint empty_actions() {\n\treturn empty_count;\n}\n\nstatic int parse_empty_args(struct action_entry *action, int args, char **argv, void **data) {\n\tstruct empty_data *empty_data;\n\tint val;\n\n\tif (args >= 2) {\n\t\tSYNTAX_ERROR(\"Empty action expects zero or one argument\\n\");\n\t\treturn 0;\n\t}\n\n\tif (args == 0 || strcmp(argv[0], \"all\") == 0)\n\t\tval = EMPTY_ALL;\n\telse if (strcmp(argv[0], \"source\") == 0)\n\t\tval = EMPTY_SOURCE;\n\telse if (strcmp(argv[0], \"excluded\") == 0)\n\t\tval = EMPTY_EXCLUDED;\n\telse {\n\t\tSYNTAX_ERROR(\"Empty action expects zero arguments, or one\" \"argument containing \\\"all\\\", \\\"source\\\", or \\\"excluded\\\"\" \"\\n\");\n\t\treturn 0;\n\t}\n\n\tempty_data = malloc(sizeof(*empty_data));\n\tif (empty_data == NULL)\n\t\tMEM_ERROR();\n\n\tempty_data->val = val;\n\t*data = empty_data;\n\n\treturn 1;\n}\n\nint eval_empty_actions(struct dir_ent *dir_ent) {\n\tint i, match = 0;\n\tstruct action_data action_data;\n\tstruct empty_data *data;\n\tstruct dir_info *dir = dir_ent->dir;\n\n\t/*\n\t * Empty action only works on empty directories\n\t */\n\tif (dir->count != 0)\n\t\treturn 0;\n\n\taction_data.name = dir_ent->name;\n\taction_data.pathname = pathname(dir_ent);\n\taction_data.subpath = subpathname(dir_ent);\n\taction_data.buf = &dir_ent->inode->buf;\n\taction_data.depth = dir_ent->our_dir->depth;\n\n\tfor (i = 0; i < empty_count && !match; i++) {\n\t\tdata = empty_spec[i].data;\n\n\t\t/*\n\t\t * determine the cause of the empty directory and evaluate\n\t\t * the empty action specified.  Three empty actions:\n\t\t * - EMPTY_SOURCE: empty action triggers only if the directory\n\t\t *  was originally empty, i.e directories that are empty\n\t\t *  only due to excluding are ignored.\n\t\t * - EMPTY_EXCLUDED: empty action triggers only if the directory\n\t\t *  is empty because of excluding, i.e. directories that\n\t\t *  were originally empty are ignored.\n\t\t * - EMPTY_ALL (the default): empty action triggers if the\n\t\t *  directory is empty, irrespective of the reason, i.e.\n\t\t *  the directory could have been originally empty or could\n\t\t *  be empty due to excluding.\n\t\t */\n\t\tif ((data->val == EMPTY_EXCLUDED && !dir->excluded) || (data->val == EMPTY_SOURCE && dir->excluded))\n\t\t\tcontinue;\n\n\t\tmatch = eval_expr(empty_spec[i].expr, &action_data);\n\t}\n\n\treturn match;\n}\n\n/*\n *  Move specific action code\n */\nstatic struct move_ent *move_list = NULL;\n\nint move_actions() {\n\treturn move_count;\n}\n\nstatic char *move_pathname(struct move_ent *move) {\n\tstruct dir_info *dest;\n\tchar *name, *pathname;\n\tint res;\n\n\tdest = (move->ops & ACTION_MOVE_MOVE) ? move->dest : move->dir_ent->our_dir;\n\tname = (move->ops & ACTION_MOVE_RENAME) ? move->name : move->dir_ent->name;\n\n\tif (dest->subpath[0] != '\\0')\n\t\tres = asprintf(&pathname, \"%s/%s\", dest->subpath, name);\n\telse\n\t\tres = asprintf(&pathname, \"/%s\", name);\n\n\tif (res == -1)\n\t\tBAD_ERROR(\"asprintf failed in move_pathname\\n\");\n\n\treturn pathname;\n}\n\nstatic char *get_comp(char **pathname) {\n\tchar *path = *pathname, *start;\n\n\twhile (*path == '/')\n\t\tpath++;\n\n\tif (*path == '\\0')\n\t\treturn NULL;\n\n\tstart = path;\n\twhile (*path != '/' && *path != '\\0')\n\t\tpath++;\n\n\t*pathname = path;\n\treturn strndup(start, path - start);\n}\n\nstatic struct dir_ent *lookup_comp(char *comp, struct dir_info *dest) {\n\tstruct dir_ent *dir_ent;\n\n\tfor (dir_ent = dest->list; dir_ent; dir_ent = dir_ent->next)\n\t\tif (strcmp(comp, dir_ent->name) == 0)\n\t\t\tbreak;\n\n\treturn dir_ent;\n}\n\nvoid eval_move(struct action_data *action_data, struct move_ent *move, struct dir_info *root, struct dir_ent *dir_ent, char *pathname) {\n\tstruct dir_info *dest, *source = dir_ent->our_dir;\n\tstruct dir_ent *comp_ent;\n\tchar *comp, *path = pathname;\n\n\t/*\n\t * Walk pathname to get the destination directory\n\t *\n\t * Like the mv command, if the last component exists and it\n\t * is a directory, then move the file into that directory,\n\t * otherwise, move the file into parent directory of the last\n\t * component and rename to the last component.\n\t */\n\tif (pathname[0] == '/')\n\t\t/* absolute pathname, walk from root directory */\n\t\tdest = root;\n\telse\n\t\t/* relative pathname, walk from current directory */\n\t\tdest = source;\n\n\tfor (comp = get_comp(&pathname); comp; free(comp), comp = get_comp(&pathname)) {\n\n\t\tif (strcmp(comp, \".\") == 0)\n\t\t\tcontinue;\n\n\t\tif (strcmp(comp, \"..\") == 0) {\n\t\t\t/* if we're in the root directory then ignore */\n\t\t\tif (dest->depth > 1)\n\t\t\t\tdest = dest->dir_ent->our_dir;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t * Look up comp in current directory, if it exists and it is a\n\t\t * directory continue walking the pathname, otherwise exit,\n\t\t * we've walked as far as we can go, normally this is because\n\t\t * we've arrived at the leaf component which we are going to\n\t\t * rename source to\n\t\t */\n\t\tcomp_ent = lookup_comp(comp, dest);\n\t\tif (comp_ent == NULL || (comp_ent->inode->buf.st_mode & S_IFMT)\n\t\t\t!= S_IFDIR)\n\t\t\tbreak;\n\n\t\tdest = comp_ent->dir;\n\t}\n\n\tif (comp) {\n\t\t/* Leaf component? If so we're renaming to this  */\n\t\tchar *remainder = get_comp(&pathname);\n\t\tfree(remainder);\n\n\t\tif (remainder) {\n\t\t\t/*\n\t\t\t * trying to move source to a subdirectory of\n\t\t\t * comp, but comp either doesn't exist, or it isn't\n\t\t\t * a directory, which is impossible\n\t\t\t */\n\t\t\tif (comp_ent == NULL)\n\t\t\t\tERROR(\"Move action: cannot move %s to %s, no \" \"such directory %s\\n\", action_data->subpath, path, comp);\n\t\t\telse\n\t\t\t\tERROR(\"Move action: cannot move %s to %s, %s \" \"is not a directory\\n\", action_data->subpath, path, comp);\n\t\t\tfree(comp);\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t * Multiple move actions triggering on one file can be merged\n\t\t * if one is a RENAME and the other is a MOVE.  Multiple RENAMEs\n\t\t * can only merge if they're doing the same thing\n\t\t */\n\t\tif (move->ops & ACTION_MOVE_RENAME) {\n\t\t\tif (strcmp(comp, move->name) != 0) {\n\t\t\t\tchar *conf_path = move_pathname(move);\n\t\t\t\tERROR(\"Move action: Cannot move %s to %s, \" \"conflicting move, already moving \" \"to %s via another move action!\\n\", action_data->subpath, path, conf_path);\n\t\t\t\tfree(conf_path);\n\t\t\t\tfree(comp);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfree(comp);\n\t\t} else {\n\t\t\tmove->name = comp;\n\t\t\tmove->ops |= ACTION_MOVE_RENAME;\n\t\t}\n\t}\n\n\tif (dest != source) {\n\t\t/*\n\t\t * Multiple move actions triggering on one file can be merged\n\t\t * if one is a RENAME and the other is a MOVE.  Multiple MOVEs\n\t\t * can only merge if they're doing the same thing\n\t\t */\n\t\tif (move->ops & ACTION_MOVE_MOVE) {\n\t\t\tif (dest != move->dest) {\n\t\t\t\tchar *conf_path = move_pathname(move);\n\t\t\t\tERROR(\"Move action: Cannot move %s to %s, \" \"conflicting move, already moving \" \"to %s via another move action!\\n\", action_data->subpath, path, conf_path);\n\t\t\t\tfree(conf_path);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tmove->dest = dest;\n\t\t\tmove->ops |= ACTION_MOVE_MOVE;\n\t\t}\n\t}\n}\n\nstatic int subdirectory(struct dir_info *source, struct dir_info *dest) {\n\tif (source == NULL)\n\t\treturn 0;\n\n\treturn strlen(source->subpath) <= strlen(dest->subpath) && (dest->subpath[strlen(source->subpath)] == '/' || dest->subpath[strlen(source->subpath)] == '\\0') && strncmp(source->subpath, dest->subpath, strlen(source->subpath)) == 0;\n}\n\nvoid eval_move_actions(struct dir_info *root, struct dir_ent *dir_ent) {\n\tint i;\n\tstruct action_data action_data;\n\tstruct move_ent *move = NULL;\n\n\taction_data.name = dir_ent->name;\n\taction_data.pathname = pathname(dir_ent);\n\taction_data.subpath = subpathname(dir_ent);\n\taction_data.buf = &dir_ent->inode->buf;\n\taction_data.depth = dir_ent->our_dir->depth;\n\n\t/*\n\t * Evaluate each move action against the current file.  For any\n\t * move actions that match don't actually perform the move now, but,\n\t * store it, and execute all the stored move actions together once the\n\t * directory scan is complete.  This is done to ensure each separate\n\t * move action does not nondeterministically interfere with other move\n\t * actions.  Each move action is considered to act independently, and\n\t * each move action sees the directory tree in the same state.\n\t */\n\tfor (i = 0; i < move_count; i++) {\n\t\tstruct action *action = &move_spec[i];\n\t\tint match = eval_expr(action->expr, &action_data);\n\n\t\tif (match) {\n\t\t\tif (move == NULL) {\n\t\t\t\tmove = malloc(sizeof(*move));\n\t\t\t\tif (move == NULL)\n\t\t\t\t\tMEM_ERROR();\n\n\t\t\t\tmove->ops = 0;\n\t\t\t\tmove->dir_ent = dir_ent;\n\t\t\t}\n\t\t\teval_move(&action_data, move, root, dir_ent, action->argv[0]);\n\t\t}\n\t}\n\n\tif (move) {\n\t\tstruct dir_ent *comp_ent;\n\t\tstruct dir_info *dest;\n\t\tchar *name;\n\n\t\t/*\n\t\t * Move contains the result of all triggered move actions.\n\t\t * Check the destination doesn't already exist\n\t\t */\n\t\tif (move->ops == 0) {\n\t\t\tfree(move);\n\t\t\treturn;\n\t\t}\n\n\t\tdest = (move->ops & ACTION_MOVE_MOVE) ? move->dest : dir_ent->our_dir;\n\t\tname = (move->ops & ACTION_MOVE_RENAME) ? move->name : dir_ent->name;\n\t\tcomp_ent = lookup_comp(name, dest);\n\t\tif (comp_ent) {\n\t\t\tchar *conf_path = move_pathname(move);\n\t\t\tERROR(\"Move action: Cannot move %s to %s, \" \"destination already exists\\n\", action_data.subpath, conf_path);\n\t\t\tfree(conf_path);\n\t\t\tfree(move);\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t * If we're moving a directory, check we're not moving it to a\n\t\t * subdirectory of itself\n\t\t */\n\t\tif (subdirectory(dir_ent->dir, dest)) {\n\t\t\tchar *conf_path = move_pathname(move);\n\t\t\tERROR(\"Move action: Cannot move %s to %s, this is a \" \"subdirectory of itself\\n\", action_data.subpath, conf_path);\n\t\t\tfree(conf_path);\n\t\t\tfree(move);\n\t\t\treturn;\n\t\t}\n\t\tmove->next = move_list;\n\t\tmove_list = move;\n\t}\n}\n\nstatic void move_dir(struct dir_ent *dir_ent) {\n\tstruct dir_info *dir = dir_ent->dir;\n\tstruct dir_ent *comp_ent;\n\n\t/* update our directory's subpath name */\n\tfree(dir->subpath);\n\tdir->subpath = strdup(subpathname(dir_ent));\n\n\t/* recursively update the subpaths of any sub-directories */\n\tfor (comp_ent = dir->list; comp_ent; comp_ent = comp_ent->next)\n\t\tif (comp_ent->dir)\n\t\t\tmove_dir(comp_ent);\n}\n\nstatic void move_file(struct move_ent *move_ent) {\n\tstruct dir_ent *dir_ent = move_ent->dir_ent;\n\n\tif (move_ent->ops & ACTION_MOVE_MOVE) {\n\t\tstruct dir_ent *comp_ent, *prev = NULL;\n\t\tstruct dir_info *source = dir_ent->our_dir, *dest = move_ent->dest;\n\t\tchar *filename = pathname(dir_ent);\n\n\t\t/*\n\t\t * If we're moving a directory, check we're not moving it to a\n\t\t * subdirectory of itself\n\t\t */\n\t\tif (subdirectory(dir_ent->dir, dest)) {\n\t\t\tchar *conf_path = move_pathname(move_ent);\n\t\t\tERROR(\"Move action: Cannot move %s to %s, this is a \" \"subdirectory of itself\\n\", subpathname(dir_ent), conf_path);\n\t\t\tfree(conf_path);\n\t\t\treturn;\n\t\t}\n\n\t\t/* Remove the file from source directory */\n\t\tfor (comp_ent = source->list; comp_ent != dir_ent; prev = comp_ent, comp_ent = comp_ent->next) ;\n\n\t\tif (prev)\n\t\t\tprev->next = comp_ent->next;\n\t\telse\n\t\t\tsource->list = comp_ent->next;\n\n\t\tsource->count--;\n\t\tif ((comp_ent->inode->buf.st_mode & S_IFMT) == S_IFDIR)\n\t\t\tsource->directory_count--;\n\n\t\t/* Add the file to dest directory */\n\t\tcomp_ent->next = dest->list;\n\t\tdest->list = comp_ent;\n\t\tcomp_ent->our_dir = dest;\n\n\t\tdest->count++;\n\t\tif ((comp_ent->inode->buf.st_mode & S_IFMT) == S_IFDIR)\n\t\t\tdest->directory_count++;\n\n\t\t/*\n\t\t * We've moved the file, and so we can't now use the\n\t\t * parent directory's pathname to calculate the pathname\n\t\t */\n\t\tif (dir_ent->nonstandard_pathname == NULL) {\n\t\t\tdir_ent->nonstandard_pathname = strdup(filename);\n\t\t\tif (dir_ent->source_name) {\n\t\t\t\tfree(dir_ent->source_name);\n\t\t\t\tdir_ent->source_name = NULL;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (move_ent->ops & ACTION_MOVE_RENAME) {\n\t\t/*\n\t\t * If we're using name in conjunction with the parent\n\t\t * directory's pathname to calculate the pathname, we need\n\t\t * to use source_name to override.  Otherwise it's already being\n\t\t * over-ridden\n\t\t */\n\t\tif (dir_ent->nonstandard_pathname == NULL && dir_ent->source_name == NULL)\n\t\t\tdir_ent->source_name = dir_ent->name;\n\t\telse\n\t\t\tfree(dir_ent->name);\n\n\t\tdir_ent->name = move_ent->name;\n\t}\n\n\tif (dir_ent->dir)\n\t\t/*\n\t\t * dir_ent is a directory, and we have to recursively fix-up\n\t\t * its subpath, and the subpaths of all of its sub-directories\n\t\t */\n\t\tmove_dir(dir_ent);\n}\n\nvoid do_move_actions() {\n\twhile (move_list) {\n\t\tstruct move_ent *temp = move_list;\n\t\tstruct dir_info *dest = (move_list->ops & ACTION_MOVE_MOVE) ? move_list->dest : move_list->dir_ent->our_dir;\n\t\tchar *name = (move_list->ops & ACTION_MOVE_RENAME) ? move_list->name : move_list->dir_ent->name;\n\t\tstruct dir_ent *comp_ent = lookup_comp(name, dest);\n\t\tif (comp_ent) {\n\t\t\tchar *conf_path = move_pathname(move_list);\n\t\t\tERROR(\"Move action: Cannot move %s to %s, \" \"destination already exists\\n\", subpathname(move_list->dir_ent), conf_path);\n\t\t\tfree(conf_path);\n\t\t} else\n\t\t\tmove_file(move_list);\n\n\t\tmove_list = move_list->next;\n\t\tfree(temp);\n\t}\n}\n\n/*\n * General test evaluation code\n */\n\n/*\n * A number can be of the form [range]number[size]\n * [range] is either:\n *\t'<' or '-', match on less than number\n *\t'>' or '+', match on greater than number\n *\t'' (nothing), match on exactly number\n * [size] is either:\n *\t'' (nothing), number\n *\t'k' or 'K', number * 2^10\n * \t'm' or 'M', number * 2^20\n *\t'g' or 'G', number * 2^30\n */\nstatic int parse_number(char *start, long long *size, int *range, char **error) {\n\tchar *end;\n\tlong long number;\n\n\tif (*start == '>' || *start == '+') {\n\t\t*range = NUM_GREATER;\n\t\tstart++;\n\t} else if (*start == '<' || *start == '-') {\n\t\t*range = NUM_LESS;\n\t\tstart++;\n\t} else\n\t\t*range = NUM_EQ;\n\n\terrno = 0;\t\t\t\t\t/* To enable failure after call to be determined */\n\tnumber = strtoll(start, &end, 10);\n\n\tif ((errno == ERANGE && (number == LLONG_MAX || number == LLONG_MIN))\n\t\t|| (errno != 0 && number == 0)) {\n\t\t/* long long underflow or overflow in conversion, or other\n\t\t * conversion error.\n\t\t * Note: we don't check for LLONG_MIN and LLONG_MAX only\n\t\t * because strtoll can validly return that if the\n\t\t * user used these values\n\t\t */\n\t\t*error = \"Long long underflow, overflow or other conversion \" \"error\";\n\t\treturn 0;\n\t}\n\n\tif (end == start) {\n\t\t/* Couldn't read any number  */\n\t\t*error = \"Number expected\";\n\t\treturn 0;\n\t}\n\n\tswitch (end[0]) {\n\tcase 'g':\n\tcase 'G':\n\t\tnumber *= 1024;\n\tcase 'm':\n\tcase 'M':\n\t\tnumber *= 1024;\n\tcase 'k':\n\tcase 'K':\n\t\tnumber *= 1024;\n\n\t\tif (end[1] != '\\0') {\n\t\t\t*error = \"Trailing junk after size specifier\";\n\t\t\treturn 0;\n\t\t}\n\n\t\tbreak;\n\tcase '\\0':\n\t\tbreak;\n\tdefault:\n\t\t*error = \"Trailing junk after number\";\n\t\treturn 0;\n\t}\n\n\t*size = number;\n\n\treturn 1;\n}\n\nstatic int parse_number_arg(struct test_entry *test, struct atom *atom) {\n\tstruct test_number_arg *number;\n\tlong long size;\n\tint range;\n\tchar *error;\n\tint res = parse_number(atom->argv[0], &size, &range, &error);\n\n\tif (res == 0) {\n\t\tTEST_SYNTAX_ERROR(test, 0, \"%s\\n\", error);\n\t\treturn 0;\n\t}\n\n\tnumber = malloc(sizeof(*number));\n\tif (number == NULL)\n\t\tMEM_ERROR();\n\n\tnumber->range = range;\n\tnumber->size = size;\n\n\tatom->data = number;\n\n\treturn 1;\n}\n\nstatic int parse_range_args(struct test_entry *test, struct atom *atom) {\n\tstruct test_range_args *range;\n\tlong long start, end;\n\tint type;\n\tint res;\n\tchar *error;\n\n\tres = parse_number(atom->argv[0], &start, &type, &error);\n\tif (res == 0) {\n\t\tTEST_SYNTAX_ERROR(test, 0, \"%s\\n\", error);\n\t\treturn 0;\n\t}\n\n\tif (type != NUM_EQ) {\n\t\tTEST_SYNTAX_ERROR(test, 0, \"Range specifier (<, >, -, +) not \" \"expected\\n\");\n\t\treturn 0;\n\t}\n\n\tres = parse_number(atom->argv[1], &end, &type, &error);\n\tif (res == 0) {\n\t\tTEST_SYNTAX_ERROR(test, 1, \"%s\\n\", error);\n\t\treturn 0;\n\t}\n\n\tif (type != NUM_EQ) {\n\t\tTEST_SYNTAX_ERROR(test, 1, \"Range specifier (<, >, -, +) not \" \"expected\\n\");\n\t\treturn 0;\n\t}\n\n\trange = malloc(sizeof(*range));\n\tif (range == NULL)\n\t\tMEM_ERROR();\n\n\trange->start = start;\n\trange->end = end;\n\n\tatom->data = range;\n\n\treturn 1;\n}\n\n/*\n * Generic test code macro\n */\n#define TEST_FN(NAME, MATCH, CODE) \\\nstatic int NAME##_fn(struct atom *atom, struct action_data *action_data) \\\n{ \\\n\t/* test operates on MATCH file types only */ \\\n\tif (!(action_data->buf->st_mode & MATCH)) \\\n\t\treturn 0; \\\n \\\n\tCODE \\\n}\n\n/*\n * Generic test code macro testing VAR for size (eq, less than, greater than)\n */\n#define TEST_VAR_FN(NAME, MATCH, VAR) TEST_FN(NAME, MATCH, \\\n\t{ \\\n\tint match = 0; \\\n\tstruct test_number_arg *number = atom->data; \\\n\t\\\n\tswitch (number->range) { \\\n\tcase NUM_EQ: \\\n\t\tmatch = VAR == number->size; \\\n\t\tbreak; \\\n\tcase NUM_LESS: \\\n\t\tmatch = VAR < number->size; \\\n\t\tbreak; \\\n\tcase NUM_GREATER: \\\n\t\tmatch = VAR > number->size; \\\n\t\tbreak; \\\n\t} \\\n\t\\\n\treturn match; \\\n\t})\n\n/*\n * Generic test code macro testing VAR for range [x, y] (value between x and y\n * inclusive).\n */\n#define TEST_VAR_RANGE_FN(NAME, MATCH, VAR) TEST_FN(NAME##_range, MATCH, \\\n\t{ \\\n\tstruct test_range_args *range = atom->data; \\\n\t\\\n\treturn range->start <= VAR && VAR <= range->end; \\\n\t})\n\n/*\n * Name, Pathname and Subpathname test specific code\n */\n\n/*\n * Add a leading \"/\" if subpathname and pathname lacks it\n */\nstatic int check_pathname(struct test_entry *test, struct atom *atom) {\n\tint res;\n\tchar *name;\n\n\tif (atom->argv[0][0] != '/') {\n\t\tres = asprintf(&name, \"/%s\", atom->argv[0]);\n\t\tif (res == -1)\n\t\t\tBAD_ERROR(\"asprintf failed in check_pathname\\n\");\n\n\t\tfree(atom->argv[0]);\n\t\tatom->argv[0] = name;\n\t}\n\n\treturn 1;\n}\n\nTEST_FN(name, ACTION_ALL_LNK, return fnmatch(atom->argv[0], action_data->name, FNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) == 0;)\n\n\tTEST_FN(pathname, ACTION_ALL_LNK, return fnmatch(atom->argv[0], action_data->subpath, FNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) == 0;)\n\nstatic int count_components(char *path) {\n\tint count;\n\n\tfor (count = 0; *path != '\\0'; count++) {\n\t\twhile (*path == '/')\n\t\t\tpath++;\n\n\t\twhile (*path != '\\0' && *path != '/')\n\t\t\tpath++;\n\t}\n\n\treturn count;\n}\n\nstatic char *get_start(char *s, int n) {\n\tint count;\n\tchar *path = s;\n\n\tfor (count = 0; *path != '\\0' && count < n; count++) {\n\t\twhile (*path == '/')\n\t\t\tpath++;\n\n\t\twhile (*path != '\\0' && *path != '/')\n\t\t\tpath++;\n\t}\n\n\tif (count == n)\n\t\t*path = '\\0';\n\n\treturn s;\n}\n\nstatic int subpathname_fn(struct atom *atom, struct action_data *action_data) {\n\treturn fnmatch(atom->argv[0], get_start(strdupa(action_data->subpath), count_components(atom->argv[0])), FNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) == 0;\n}\n\nTEST_VAR_FN(filesize, ACTION_REG, action_data->buf->st_size)\n\n\tTEST_VAR_FN(dirsize, ACTION_DIR, action_data->buf->st_size)\n\n\tTEST_VAR_FN(size, ACTION_ALL_LNK, action_data->buf->st_size)\n\n\tTEST_VAR_FN(inode, ACTION_ALL_LNK, action_data->buf->st_ino)\n\n\tTEST_VAR_FN(nlink, ACTION_ALL_LNK, action_data->buf->st_nlink)\n\n\tTEST_VAR_FN(fileblocks, ACTION_REG, action_data->buf->st_blocks)\n\n\tTEST_VAR_FN(dirblocks, ACTION_DIR, action_data->buf->st_blocks)\n\n\tTEST_VAR_FN(blocks, ACTION_ALL_LNK, action_data->buf->st_blocks)\n\n\tTEST_VAR_FN(gid, ACTION_ALL_LNK, action_data->buf->st_gid)\n\n\tTEST_VAR_FN(uid, ACTION_ALL_LNK, action_data->buf->st_uid)\n\n\tTEST_VAR_FN(depth, ACTION_ALL_LNK, action_data->depth)\n\n\tTEST_VAR_RANGE_FN(filesize, ACTION_REG, action_data->buf->st_size)\n\n\tTEST_VAR_RANGE_FN(dirsize, ACTION_DIR, action_data->buf->st_size)\n\n\tTEST_VAR_RANGE_FN(size, ACTION_ALL_LNK, action_data->buf->st_size)\n\n\tTEST_VAR_RANGE_FN(inode, ACTION_ALL_LNK, action_data->buf->st_ino)\n\n\tTEST_VAR_RANGE_FN(nlink, ACTION_ALL_LNK, action_data->buf->st_nlink)\n\n\tTEST_VAR_RANGE_FN(fileblocks, ACTION_REG, action_data->buf->st_blocks)\n\n\tTEST_VAR_RANGE_FN(dirblocks, ACTION_DIR, action_data->buf->st_blocks)\n\n\tTEST_VAR_RANGE_FN(blocks, ACTION_ALL_LNK, action_data->buf->st_blocks)\n\n\tTEST_VAR_RANGE_FN(gid, ACTION_ALL_LNK, action_data->buf->st_gid)\n\n\tTEST_VAR_RANGE_FN(uid, ACTION_ALL_LNK, action_data->buf->st_uid)\n\n\tTEST_VAR_RANGE_FN(depth, ACTION_ALL_LNK, action_data->depth)\n\n/*\n * Type test specific code\n */\nstruct type_entry type_table[] = {\n\t{S_IFSOCK, 's'},\n\t{S_IFLNK, 'l'},\n\t{S_IFREG, 'f'},\n\t{S_IFBLK, 'b'},\n\t{S_IFDIR, 'd'},\n\t{S_IFCHR, 'c'},\n\t{S_IFIFO, 'p'},\n\t{0, 0},\n};\n\nstatic int parse_type_arg(struct test_entry *test, struct atom *atom) {\n\tint i;\n\n\tif (strlen(atom->argv[0]) != 1)\n\t\tgoto failed;\n\n\tfor (i = 0; type_table[i].type != 0; i++)\n\t\tif (type_table[i].type == atom->argv[0][0])\n\t\t\tbreak;\n\n\tatom->data = &type_table[i];\n\n\tif (type_table[i].type != 0)\n\t\treturn 1;\n\n failed:\n\tTEST_SYNTAX_ERROR(test, 0, \"Unexpected file type, expected 'f', 'd', \" \"'c', 'b', 'l', 's' or 'p'\\n\");\n\treturn 0;\n}\n\nstatic int type_fn(struct atom *atom, struct action_data *action_data) {\n\tstruct type_entry *type = atom->data;\n\n\treturn (action_data->buf->st_mode & S_IFMT) == type->value;\n}\n\n/*\n * True test specific code\n */\nstatic int true_fn(struct atom *atom, struct action_data *action_data) {\n\treturn 1;\n}\n\n/*\n *  False test specific code\n */\nstatic int false_fn(struct atom *atom, struct action_data *action_data) {\n\treturn 0;\n}\n\n/*\n *  File test specific code\n */\nstatic int parse_file_arg(struct test_entry *test, struct atom *atom) {\n\tint res;\n\tregex_t *preg = malloc(sizeof(regex_t));\n\n\tif (preg == NULL)\n\t\tMEM_ERROR();\n\n\tres = regcomp(preg, atom->argv[0], REG_EXTENDED);\n\tif (res) {\n\t\tchar str[1024];\t\t\t/* overflow safe */\n\n\t\tregerror(res, preg, str, 1024);\n\t\tfree(preg);\n\t\tTEST_SYNTAX_ERROR(test, 0, \"invalid regex \\\"%s\\\" because \" \"\\\"%s\\\"\\n\", atom->argv[0], str);\n\t\treturn 0;\n\t}\n\n\tatom->data = preg;\n\n\treturn 1;\n}\n\nstatic int file_fn(struct atom *atom, struct action_data *action_data) {\n\tint child, res, size = 0, status;\n\tint pipefd[2];\n\tchar *buffer = NULL;\n\tregex_t *preg = atom->data;\n\n\tres = pipe(pipefd);\n\tif (res == -1)\n\t\tBAD_ERROR(\"file_fn pipe failed\\n\");\n\n\tchild = fork();\n\tif (child == -1)\n\t\tBAD_ERROR(\"file_fn fork_failed\\n\");\n\n\tif (child == 0) {\n\t\t/*\n\t\t * Child process\n\t\t * Connect stdout to pipefd[1] and execute file command\n\t\t */\n\t\tclose(STDOUT_FILENO);\n\t\tres = dup(pipefd[1]);\n\t\tif (res == -1)\n\t\t\texit(EXIT_FAILURE);\n\n\t\texeclp(\"file\", \"file\", \"-b\", action_data->pathname, (char *)NULL);\n\t\texit(EXIT_FAILURE);\n\t}\n\n\t/*\n\t * Parent process.  Read stdout from file command\n\t */\n\tclose(pipefd[1]);\n\n\tdo {\n\t\tbuffer = realloc(buffer, size + 512);\n\t\tif (buffer == NULL)\n\t\t\tMEM_ERROR();\n\n\t\tres = read_bytes(pipefd[0], buffer + size, 512);\n\n\t\tif (res == -1)\n\t\t\tBAD_ERROR(\"file_fn pipe read error\\n\");\n\n\t\tsize += 512;\n\n\t} while (res == 512);\n\n\tsize = size + res - 512;\n\n\tbuffer[size] = '\\0';\n\n\tres = waitpid(child, &status, 0);\n\n\tif (res == -1)\n\t\tBAD_ERROR(\"file_fn waitpid failed\\n\");\n\n\tif (!WIFEXITED(status) || WEXITSTATUS(status) != 0)\n\t\tBAD_ERROR(\"file_fn file returned error\\n\");\n\n\tclose(pipefd[0]);\n\n\tres = regexec(preg, buffer, (size_t) 0, NULL, 0);\n\n\tfree(buffer);\n\n\treturn res == 0;\n}\n\n/*\n *  Exec test specific code\n */\nstatic int exec_fn(struct atom *atom, struct action_data *action_data) {\n\tint child, i, res, status;\n\n\tchild = fork();\n\tif (child == -1)\n\t\tBAD_ERROR(\"exec_fn fork_failed\\n\");\n\n\tif (child == 0) {\n\t\t/*\n\t\t * Child process\n\t\t * redirect stdin, stdout & stderr to /dev/null and\n\t\t * execute atom->argv[0]\n\t\t */\n\t\tint fd = open(\"/dev/null\", O_RDWR);\n\t\tif (fd == -1)\n\t\t\texit(EXIT_FAILURE);\n\n\t\tclose(STDIN_FILENO);\n\t\tclose(STDOUT_FILENO);\n\t\tclose(STDERR_FILENO);\n\t\tfor (i = 0; i < 3; i++) {\n\t\t\tres = dup(fd);\n\t\t\tif (res == -1)\n\t\t\t\texit(EXIT_FAILURE);\n\t\t}\n\t\tclose(fd);\n\n\t\t/*\n\t\t * Create environment variables\n\t\t * NAME: name of file\n\t\t * PATHNAME: pathname of file relative to squashfs root\n\t\t * SOURCE_PATHNAME: the pathname of the file in the source\n\t\t *                  directory\n\t\t */\n\t\tres = setenv(\"NAME\", action_data->name, 1);\n\t\tif (res == -1)\n\t\t\texit(EXIT_FAILURE);\n\n\t\tres = setenv(\"PATHNAME\", action_data->subpath, 1);\n\t\tif (res == -1)\n\t\t\texit(EXIT_FAILURE);\n\n\t\tres = setenv(\"SOURCE_PATHNAME\", action_data->pathname, 1);\n\t\tif (res == -1)\n\t\t\texit(EXIT_FAILURE);\n\n\t\texecl(\"/bin/sh\", \"sh\", \"-c\", atom->argv[0], (char *)NULL);\n\t\texit(EXIT_FAILURE);\n\t}\n\n\t/*\n\t * Parent process.\n\t */\n\n\tres = waitpid(child, &status, 0);\n\n\tif (res == -1)\n\t\tBAD_ERROR(\"exec_fn waitpid failed\\n\");\n\n\treturn WIFEXITED(status) ? WEXITSTATUS(status) == 0 : 0;\n}\n\n#ifdef SQUASHFS_TRACE\nstatic void dump_parse_tree(struct expr *expr) {\n\tif (expr->type == ATOM_TYPE) {\n\t\tint i;\n\n\t\tprintf(\"%s(\", expr->atom.test->name);\n\t\tfor (i = 0; i < expr->atom.test->args; i++) {\n\t\t\tprintf(\"%s\", expr->atom.argv[i]);\n\t\t\tif (i + 1 < expr->atom.test->args)\n\t\t\t\tprintf(\",\");\n\t\t}\n\t\tprintf(\")\");\n\t} else if (expr->type == UNARY_TYPE) {\n\t\tprintf(\"%s\", token_table[expr->unary_op.op].string);\n\t\tdump_parse_tree(expr->unary_op.expr);\n\t} else {\n\t\tprintf(\"(\");\n\t\tdump_parse_tree(expr->expr_op.lhs);\n\t\tprintf(\"%s\", token_table[expr->expr_op.op].string);\n\t\tdump_parse_tree(expr->expr_op.rhs);\n\t\tprintf(\")\");\n\t}\n}\n\nvoid dump_action_list(struct action *spec_list, int spec_count) {\n\tint i;\n\n\tfor (i = 0; i < spec_count; i++) {\n\t\tprintf(\"%s\", spec_list[i].action->name);\n\t\tif (spec_list[i].action->args) {\n\t\t\tint n;\n\n\t\t\tprintf(\"(\");\n\t\t\tfor (n = 0; n < spec_list[i].action->args; n++) {\n\t\t\t\tprintf(\"%s\", spec_list[i].argv[n]);\n\t\t\t\tif (n + 1 < spec_list[i].action->args)\n\t\t\t\t\tprintf(\",\");\n\t\t\t}\n\t\t\tprintf(\")\");\n\t\t}\n\t\tprintf(\"=\");\n\t\tdump_parse_tree(spec_list[i].expr);\n\t\tprintf(\"\\n\");\n\t}\n}\n\nvoid dump_actions() {\n\tdump_action_list(exclude_spec, exclude_count);\n\tdump_action_list(fragment_spec, fragment_count);\n\tdump_action_list(other_spec, other_count);\n\tdump_action_list(move_spec, move_count);\n\tdump_action_list(empty_spec, empty_count);\n}\n#else\nvoid dump_actions() {\n}\n#endif\n\nstatic struct test_entry test_table[] = {\n\t{\"name\", 1, name_fn},\n\t{\"pathname\", 1, pathname_fn, check_pathname},\n\t{\"subpathname\", 1, subpathname_fn, check_pathname},\n\t{\"filesize\", 1, filesize_fn, parse_number_arg},\n\t{\"dirsize\", 1, dirsize_fn, parse_number_arg},\n\t{\"size\", 1, size_fn, parse_number_arg},\n\t{\"inode\", 1, inode_fn, parse_number_arg},\n\t{\"nlink\", 1, nlink_fn, parse_number_arg},\n\t{\"fileblocks\", 1, fileblocks_fn, parse_number_arg},\n\t{\"dirblocks\", 1, dirblocks_fn, parse_number_arg},\n\t{\"blocks\", 1, blocks_fn, parse_number_arg},\n\t{\"gid\", 1, gid_fn, parse_number_arg},\n\t{\"uid\", 1, uid_fn, parse_number_arg},\n\t{\"depth\", 1, depth_fn, parse_number_arg},\n\t{\"filesize_range\", 2, filesize_range_fn, parse_range_args},\n\t{\"dirsize_range\", 2, dirsize_range_fn, parse_range_args},\n\t{\"size_range\", 2, size_range_fn, parse_range_args},\n\t{\"inode_range\", 2, inode_range_fn, parse_range_args},\n\t{\"nlink_range\", 2, nlink_range_fn, parse_range_args},\n\t{\"fileblocks_range\", 2, fileblocks_range_fn, parse_range_args},\n\t{\"dirblocks_range\", 2, dirblocks_range_fn, parse_range_args},\n\t{\"blocks_range\", 2, blocks_range_fn, parse_range_args},\n\t{\"gid_range\", 2, gid_range_fn, parse_range_args},\n\t{\"uid_range\", 2, uid_range_fn, parse_range_args},\n\t{\"depth_range\", 2, depth_range_fn, parse_range_args},\n\t{\"type\", 1, type_fn, parse_type_arg},\n\t{\"true\", 0, true_fn, NULL},\n\t{\"false\", 0, false_fn, NULL},\n\t{\"file\", 1, file_fn, parse_file_arg},\n\t{\"exec\", 1, exec_fn, NULL},\n\t{\"\", -1}\n};\n\nstatic struct action_entry action_table[] = {\n\t{\"fragment\", FRAGMENT_ACTION, 1, ACTION_REG, NULL, NULL},\n\t{\"exclude\", EXCLUDE_ACTION, 0, ACTION_ALL_LNK, NULL, NULL},\n\t{\"fragments\", FRAGMENTS_ACTION, 0, ACTION_REG, NULL, frag_action},\n\t{\"no-fragments\", NO_FRAGMENTS_ACTION, 0, ACTION_REG, NULL,\n\t no_frag_action},\n\t{\"always-use-fragments\", ALWAYS_FRAGS_ACTION, 0, ACTION_REG, NULL,\n\t always_frag_action},\n\t{\"dont-always-use-fragments\", NO_ALWAYS_FRAGS_ACTION, 0, ACTION_REG,\n\t NULL, no_always_frag_action},\n\t{\"compressed\", COMPRESSED_ACTION, 0, ACTION_REG, NULL, comp_action},\n\t{\"uncompressed\", UNCOMPRESSED_ACTION, 0, ACTION_REG, NULL,\n\t uncomp_action},\n\t{\"uid\", UID_ACTION, 1, ACTION_ALL_LNK, parse_uid_args, uid_action},\n\t{\"gid\", GID_ACTION, 1, ACTION_ALL_LNK, parse_gid_args, gid_action},\n\t{\"guid\", GUID_ACTION, 2, ACTION_ALL_LNK, parse_guid_args, guid_action},\n\t{\"mode\", MODE_ACTION, -2, ACTION_ALL, parse_mode_args, mode_action},\n\t{\"empty\", EMPTY_ACTION, -2, ACTION_DIR, parse_empty_args, NULL},\n\t{\"move\", MOVE_ACTION, -2, ACTION_ALL_LNK, NULL, NULL},\n\t{\"\", 0, -1, 0, NULL, NULL}\n};\n"
  },
  {
    "path": "src/squashfs/caches-queues-lists.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * caches-queues-lists.c\n */\n\n#include <pthread.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n\n#include \"error.h\"\n#include \"caches-queues-lists.h\"\n\nextern int add_overflow(int, int);\nextern int multiply_overflow(int, int);\n\n#define TRUE 1\n#define FALSE 0\n\nstruct queue *queue_init(int size) {\n\tstruct queue *queue = malloc(sizeof(struct queue));\n\n\tif (queue == NULL)\n\t\tMEM_ERROR();\n\n\tif (add_overflow(size, 1) || multiply_overflow(size + 1, sizeof(void *)))\n\t\tBAD_ERROR(\"Size too large in queue_init\\n\");\n\n\tqueue->data = malloc(sizeof(void *) * (size + 1));\n\tif (queue->data == NULL)\n\t\tMEM_ERROR();\n\n\tqueue->size = size + 1;\n\tqueue->readp = queue->writep = 0;\n\tpthread_mutex_init(&queue->mutex, NULL);\n\tpthread_cond_init(&queue->empty, NULL);\n\tpthread_cond_init(&queue->full, NULL);\n\n\treturn queue;\n}\n\nvoid queue_put(struct queue *queue, void *data) {\n\tint nextp;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &queue->mutex);\n\tpthread_mutex_lock(&queue->mutex);\n\n\twhile ((nextp = (queue->writep + 1) % queue->size) == queue->readp)\n\t\tpthread_cond_wait(&queue->full, &queue->mutex);\n\n\tqueue->data[queue->writep] = data;\n\tqueue->writep = nextp;\n\tpthread_cond_signal(&queue->empty);\n\tpthread_cleanup_pop(1);\n}\n\nvoid *queue_get(struct queue *queue) {\n\tvoid *data;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &queue->mutex);\n\tpthread_mutex_lock(&queue->mutex);\n\n\twhile (queue->readp == queue->writep)\n\t\tpthread_cond_wait(&queue->empty, &queue->mutex);\n\n\tdata = queue->data[queue->readp];\n\tqueue->readp = (queue->readp + 1) % queue->size;\n\tpthread_cond_signal(&queue->full);\n\tpthread_cleanup_pop(1);\n\n\treturn data;\n}\n\nint queue_empty(struct queue *queue) {\n\tint empty;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &queue->mutex);\n\tpthread_mutex_lock(&queue->mutex);\n\n\tempty = queue->readp == queue->writep;\n\n\tpthread_cleanup_pop(1);\n\n\treturn empty;\n}\n\nvoid queue_flush(struct queue *queue) {\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &queue->mutex);\n\tpthread_mutex_lock(&queue->mutex);\n\n\tqueue->readp = queue->writep;\n\n\tpthread_cleanup_pop(1);\n}\n\nvoid dump_queue(struct queue *queue) {\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &queue->mutex);\n\tpthread_mutex_lock(&queue->mutex);\n\n\tprintf(\"\\tMax size %d, size %d%s\\n\", queue->size - 1, queue->readp <= queue->writep ? queue->writep - queue->readp : queue->size - queue->readp + queue->writep, queue->readp == queue->writep ? \" (EMPTY)\" : ((queue->writep + 1) % queue->size) == queue->readp ? \" (FULL)\" : \"\");\n\n\tpthread_cleanup_pop(1);\n}\n\n/* define seq queue hash tables */\n#define CALCULATE_SEQ_HASH(N) CALCULATE_HASH(N)\n\n/* Called with the seq queue mutex held */\nINSERT_HASH_TABLE(seq, struct seq_queue, CALCULATE_SEQ_HASH, sequence, seq)\n\n/* Called with the cache mutex held */\nREMOVE_HASH_TABLE(seq, struct seq_queue, CALCULATE_SEQ_HASH, sequence, seq);\n\nstatic unsigned int sequence = 0;\n\nstruct seq_queue *seq_queue_init() {\n\tstruct seq_queue *queue = malloc(sizeof(struct seq_queue));\n\tif (queue == NULL)\n\t\tMEM_ERROR();\n\n\tmemset(queue, 0, sizeof(struct seq_queue));\n\n\tpthread_mutex_init(&queue->mutex, NULL);\n\tpthread_cond_init(&queue->wait, NULL);\n\n\treturn queue;\n}\n\nvoid seq_queue_put(struct seq_queue *queue, struct file_buffer *entry) {\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &queue->mutex);\n\tpthread_mutex_lock(&queue->mutex);\n\n\tinsert_seq_hash_table(queue, entry);\n\n\tif (entry->fragment)\n\t\tqueue->fragment_count++;\n\telse\n\t\tqueue->block_count++;\n\n\tif (entry->sequence == sequence)\n\t\tpthread_cond_signal(&queue->wait);\n\n\tpthread_cleanup_pop(1);\n}\n\nstruct file_buffer *seq_queue_get(struct seq_queue *queue) {\n\t/*\n\t * Look-up buffer matching sequence in the queue, if found return\n\t * it, otherwise wait until it arrives\n\t */\n\tint hash = CALCULATE_SEQ_HASH(sequence);\n\tstruct file_buffer *entry;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &queue->mutex);\n\tpthread_mutex_lock(&queue->mutex);\n\n\twhile (1) {\n\t\tfor (entry = queue->hash_table[hash]; entry; entry = entry->seq_next)\n\t\t\tif (entry->sequence == sequence)\n\t\t\t\tbreak;\n\n\t\tif (entry) {\n\t\t\t/*\n\t\t\t * found the buffer in the queue, decrement the\n\t\t\t * appropriate count, and remove from hash list\n\t\t\t */\n\t\t\tif (entry->fragment)\n\t\t\t\tqueue->fragment_count--;\n\t\t\telse\n\t\t\t\tqueue->block_count--;\n\n\t\t\tremove_seq_hash_table(queue, entry);\n\n\t\t\tsequence++;\n\n\t\t\tbreak;\n\t\t}\n\n\t\t/* entry not found, wait for it to arrive */\n\t\tpthread_cond_wait(&queue->wait, &queue->mutex);\n\t}\n\n\tpthread_cleanup_pop(1);\n\n\treturn entry;\n}\n\nvoid seq_queue_flush(struct seq_queue *queue) {\n\tint i;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &queue->mutex);\n\tpthread_mutex_lock(&queue->mutex);\n\n\tfor (i = 0; i < HASH_SIZE; i++)\n\t\tqueue->hash_table[i] = NULL;\n\n\tqueue->fragment_count = queue->block_count = 0;\n\n\tpthread_cleanup_pop(1);\n}\n\nvoid dump_seq_queue(struct seq_queue *queue, int fragment_queue) {\n\tint size;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &queue->mutex);\n\tpthread_mutex_lock(&queue->mutex);\n\n\tsize = fragment_queue ? queue->fragment_count : queue->block_count;\n\n\tprintf(\"\\tMax size unlimited, size %d%s\\n\", size, size == 0 ? \" (EMPTY)\" : \"\");\n\n\tpthread_cleanup_pop(1);\n}\n\n/* define cache hash tables */\n#define CALCULATE_CACHE_HASH(N) CALCULATE_HASH(llabs(N))\n\n/* Called with the cache mutex held */\nINSERT_HASH_TABLE(cache, struct cache, CALCULATE_CACHE_HASH, index, hash)\n\n/* Called with the cache mutex held */\nREMOVE_HASH_TABLE(cache, struct cache, CALCULATE_CACHE_HASH, index, hash);\n\n/* define cache free list */\n\n/* Called with the cache mutex held */\nINSERT_LIST(free, struct file_buffer)\n\n/* Called with the cache mutex held */\nREMOVE_LIST(free, struct file_buffer)\n\nstruct cache *cache_init(int buffer_size, int max_buffers, int noshrink_lookup, int first_freelist) {\n\tstruct cache *cache = malloc(sizeof(struct cache));\n\n\tif (cache == NULL)\n\t\tMEM_ERROR();\n\n\tcache->max_buffers = max_buffers;\n\tcache->buffer_size = buffer_size;\n\tcache->count = 0;\n\tcache->used = 0;\n\tcache->free_list = NULL;\n\n\t/*\n\t * The cache will grow up to max_buffers in size in response to\n\t * an increase in readhead/number of buffers in flight.  But\n\t * once the outstanding buffers gets returned, we can either elect\n\t * to shrink the cache, or to put the freed blocks onto a free list.\n\t *\n\t * For the caches where we want to do lookup (fragment/writer),\n\t * a don't shrink policy is best, for the reader cache it\n\t * makes no sense to keep buffers around longer than necessary as\n\t * we don't do any lookup on those blocks.\n\t */\n\tcache->noshrink_lookup = noshrink_lookup;\n\n\t/*\n\t * The default use freelist before growing cache policy behaves\n\t * poorly with appending - with many duplicates the caches\n\t * do not grow due to the fact that large queues of outstanding\n\t * fragments/writer blocks do not occur, leading to small caches\n\t * and un-uncessary performance loss to frequent cache\n\t * replacement in the small caches.  Therefore with appending\n\t * change the policy to grow the caches before reusing blocks\n\t * from the freelist\n\t */\n\tcache->first_freelist = first_freelist;\n\n\tmemset(cache->hash_table, 0, sizeof(struct file_buffer *) * 65536);\n\tpthread_mutex_init(&cache->mutex, NULL);\n\tpthread_cond_init(&cache->wait_for_free, NULL);\n\tpthread_cond_init(&cache->wait_for_unlock, NULL);\n\n\treturn cache;\n}\n\nstruct file_buffer *cache_lookup(struct cache *cache, long long index) {\n\t/* Lookup block in the cache, if found return with usage count\n\t * incremented, if not found return NULL */\n\tint hash = CALCULATE_CACHE_HASH(index);\n\tstruct file_buffer *entry;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &cache->mutex);\n\tpthread_mutex_lock(&cache->mutex);\n\n\tfor (entry = cache->hash_table[hash]; entry; entry = entry->hash_next)\n\t\tif (entry->index == index)\n\t\t\tbreak;\n\n\tif (entry) {\n\t\t/* found the block in the cache, increment used count and\n\t\t * if necessary remove from free list so it won't disappear\n\t\t */\n\t\tif (entry->used == 0) {\n\t\t\tremove_free_list(&cache->free_list, entry);\n\t\t\tcache->used++;\n\t\t}\n\t\tentry->used++;\n\t}\n\n\tpthread_cleanup_pop(1);\n\n\treturn entry;\n}\n\nstatic struct file_buffer *cache_freelist(struct cache *cache) {\n\tstruct file_buffer *entry = cache->free_list;\n\n\tremove_free_list(&cache->free_list, entry);\n\n\t/* a block on the free_list is hashed */\n\tremove_cache_hash_table(cache, entry);\n\n\tcache->used++;\n\treturn entry;\n}\n\nstatic struct file_buffer *cache_alloc(struct cache *cache) {\n\tstruct file_buffer *entry = malloc(sizeof(struct file_buffer) + cache->buffer_size);\n\tif (entry == NULL)\n\t\tMEM_ERROR();\n\n\tentry->cache = cache;\n\tentry->free_prev = entry->free_next = NULL;\n\tcache->count++;\n\treturn entry;\n}\n\nstatic struct file_buffer *_cache_get(struct cache *cache, long long index, int hash) {\n\t/* Get a free block out of the cache indexed on index. */\n\tstruct file_buffer *entry = NULL;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &cache->mutex);\n\tpthread_mutex_lock(&cache->mutex);\n\n\twhile (1) {\n\t\tif (cache->noshrink_lookup) {\n\t\t\t/* first try to get a block from the free list */\n\t\t\tif (cache->first_freelist && cache->free_list)\n\t\t\t\tentry = cache_freelist(cache);\n\t\t\telse if (cache->count < cache->max_buffers) {\n\t\t\t\tentry = cache_alloc(cache);\n\t\t\t\tcache->used++;\n\t\t\t} else if (!cache->first_freelist && cache->free_list)\n\t\t\t\tentry = cache_freelist(cache);\n\t\t} else {\t\t\t\t/* shrinking non-lookup cache */\n\t\t\tif (cache->count < cache->max_buffers) {\n\t\t\t\tentry = cache_alloc(cache);\n\t\t\t\tif (cache->count > cache->max_count)\n\t\t\t\t\tcache->max_count = cache->count;\n\t\t\t}\n\t\t}\n\n\t\tif (entry)\n\t\t\tbreak;\n\n\t\t/* wait for a block */\n\t\tpthread_cond_wait(&cache->wait_for_free, &cache->mutex);\n\t}\n\n\t/* initialise block and if hash is set insert into the hash table */\n\tentry->used = 1;\n\tentry->locked = FALSE;\n\tentry->wait_on_unlock = FALSE;\n\tentry->error = FALSE;\n\tif (hash) {\n\t\tentry->index = index;\n\t\tinsert_cache_hash_table(cache, entry);\n\t}\n\n\tpthread_cleanup_pop(1);\n\n\treturn entry;\n}\n\nstruct file_buffer *cache_get(struct cache *cache, long long index) {\n\treturn _cache_get(cache, index, 1);\n}\n\nstruct file_buffer *cache_get_nohash(struct cache *cache) {\n\treturn _cache_get(cache, 0, 0);\n}\n\nvoid cache_hash(struct file_buffer *entry, long long index) {\n\tstruct cache *cache = entry->cache;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &cache->mutex);\n\tpthread_mutex_lock(&cache->mutex);\n\n\tentry->index = index;\n\tinsert_cache_hash_table(cache, entry);\n\n\tpthread_cleanup_pop(1);\n}\n\nvoid cache_block_put(struct file_buffer *entry) {\n\tstruct cache *cache;\n\n\t/*\n\t * Finished with this cache entry, once the usage count reaches zero it\n\t * can be reused.\n\t *\n\t * If noshrink_lookup is set, put the block onto the free list.\n\t * As blocks remain accessible via the hash table they can be found\n\t * getting a new lease of life before they are reused.\n\t *\n\t * if noshrink_lookup is not set then shrink the cache.\n\t */\n\n\tif (entry == NULL)\n\t\treturn;\n\n\tcache = entry->cache;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &cache->mutex);\n\tpthread_mutex_lock(&cache->mutex);\n\n\tentry->used--;\n\tif (entry->used == 0) {\n\t\tif (cache->noshrink_lookup) {\n\t\t\tinsert_free_list(&cache->free_list, entry);\n\t\t\tcache->used--;\n\t\t} else {\n\t\t\tfree(entry);\n\t\t\tcache->count--;\n\t\t}\n\n\t\t/* One or more threads may be waiting on this block */\n\t\tpthread_cond_signal(&cache->wait_for_free);\n\t}\n\n\tpthread_cleanup_pop(1);\n}\n\nvoid dump_cache(struct cache *cache) {\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &cache->mutex);\n\tpthread_mutex_lock(&cache->mutex);\n\n\tif (cache->noshrink_lookup)\n\t\tprintf(\"\\tMax buffers %d, Current size %d, Used %d,  %s\\n\", cache->max_buffers, cache->count, cache->used, cache->free_list ? \"Free buffers\" : \"No free buffers\");\n\telse\n\t\tprintf(\"\\tMax buffers %d, Current size %d, Maximum historical \" \"size %d\\n\", cache->max_buffers, cache->count, cache->max_count);\n\n\tpthread_cleanup_pop(1);\n}\n\nstruct file_buffer *cache_get_nowait(struct cache *cache, long long index) {\n\tstruct file_buffer *entry = NULL;\n\t/*\n\t * block doesn't exist, create it, but return it with the\n\t * locked flag set, so nothing tries to use it while it doesn't\n\t * contain data.\n\t *\n\t * If there's no space in the cache then return NULL.\n\t */\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &cache->mutex);\n\tpthread_mutex_lock(&cache->mutex);\n\n\t/* first try to get a block from the free list */\n\tif (cache->first_freelist && cache->free_list)\n\t\tentry = cache_freelist(cache);\n\telse if (cache->count < cache->max_buffers) {\n\t\tentry = cache_alloc(cache);\n\t\tcache->used++;\n\t} else if (!cache->first_freelist && cache->free_list)\n\t\tentry = cache_freelist(cache);\n\n\tif (entry) {\n\t\t/* initialise block and insert into the hash table */\n\t\tentry->used = 1;\n\t\tentry->locked = TRUE;\n\t\tentry->wait_on_unlock = FALSE;\n\t\tentry->error = FALSE;\n\t\tentry->index = index;\n\t\tinsert_cache_hash_table(cache, entry);\n\t}\n\n\tpthread_cleanup_pop(1);\n\n\treturn entry;\n}\n\nstruct file_buffer *cache_lookup_nowait(struct cache *cache, long long index, char *locked) {\n\t/*\n\t * Lookup block in the cache, if found return it with the locked flag\n\t * indicating whether it is currently locked.  In both cases increment\n\t * the used count.\n\t *\n\t * If it doesn't exist in the cache return NULL;\n\t */\n\tint hash = CALCULATE_CACHE_HASH(index);\n\tstruct file_buffer *entry;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &cache->mutex);\n\tpthread_mutex_lock(&cache->mutex);\n\n\t/* first check if the entry already exists */\n\tfor (entry = cache->hash_table[hash]; entry; entry = entry->hash_next)\n\t\tif (entry->index == index)\n\t\t\tbreak;\n\n\tif (entry) {\n\t\tif (entry->used == 0) {\n\t\t\tremove_free_list(&cache->free_list, entry);\n\t\t\tcache->used++;\n\t\t}\n\t\tentry->used++;\n\t\t*locked = entry->locked;\n\t}\n\n\tpthread_cleanup_pop(1);\n\n\treturn entry;\n}\n\nvoid cache_wait_unlock(struct file_buffer *buffer) {\n\tstruct cache *cache = buffer->cache;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &cache->mutex);\n\tpthread_mutex_lock(&cache->mutex);\n\n\twhile (buffer->locked) {\n\t\t/*\n\t\t * another thread is filling this in, wait until it\n\t\t * becomes unlocked.  Used has been incremented to ensure it\n\t\t * doesn't get reused.  By definition a block can't be\n\t\t * locked and unused, and so we don't need to worry\n\t\t * about it being on the freelist now, but, it may\n\t\t * become unused when unlocked unless used is\n\t\t * incremented\n\t\t */\n\t\tbuffer->wait_on_unlock = TRUE;\n\t\tpthread_cond_wait(&cache->wait_for_unlock, &cache->mutex);\n\t}\n\n\tpthread_cleanup_pop(1);\n}\n\nvoid cache_unlock(struct file_buffer *entry) {\n\tstruct cache *cache = entry->cache;\n\n\t/*\n\t * Unlock this locked cache entry.  If anything is waiting for this\n\t * to become unlocked, wake it up.\n\t */\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &cache->mutex);\n\tpthread_mutex_lock(&cache->mutex);\n\n\tentry->locked = FALSE;\n\n\tif (entry->wait_on_unlock) {\n\t\tentry->wait_on_unlock = FALSE;\n\t\tpthread_cond_broadcast(&cache->wait_for_unlock);\n\t}\n\n\tpthread_cleanup_pop(1);\n}\n"
  },
  {
    "path": "src/squashfs/compressor.c",
    "content": "/*\n *\n * Copyright (c) 2009, 2010, 2011\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * compressor.c\n */\n\n#include <stdio.h>\n#include <string.h>\n#include \"compressor.h\"\n#include \"squashfs_fs.h\"\n\n#ifndef GZIP_SUPPORT\nstatic struct compressor gzip_comp_ops = {\n\tZLIB_COMPRESSION, \"gzip\"\n};\n#else\nextern struct compressor gzip_comp_ops;\n#endif\n\n#ifndef LZMA_SUPPORT\nstatic struct compressor lzma_comp_ops = {\n\tLZMA_COMPRESSION, \"lzma\"\n};\n#else\nextern struct compressor lzma_comp_ops;\n#endif\n\n#ifndef LZO_SUPPORT\nstatic struct compressor lzo_comp_ops = {\n\tLZO_COMPRESSION, \"lzo\"\n};\n#else\nextern struct compressor lzo_comp_ops;\n#endif\n\n#ifndef LZ4_SUPPORT\nstatic struct compressor lz4_comp_ops = {\n\tLZ4_COMPRESSION, \"lz4\"\n};\n#else\nextern struct compressor lz4_comp_ops;\n#endif\n\n#ifndef XZ_SUPPORT\nstatic struct compressor xz_comp_ops = {\n\tXZ_COMPRESSION, \"xz\"\n};\n#else\nextern struct compressor xz_comp_ops;\n#endif\n\nstatic struct compressor unknown_comp_ops = {\n\t0, \"unknown\"\n};\n\nstruct compressor *compressor[] = {\n\t&gzip_comp_ops,\n\t&lzma_comp_ops,\n\t&lzo_comp_ops,\n\t&lz4_comp_ops,\n\t&xz_comp_ops,\n\t&unknown_comp_ops\n};\n\nstruct compressor *lookup_compressor(char *name) {\n\tint i;\n\n\tfor (i = 0; compressor[i]->id; i++)\n\t\tif (strcmp(compressor[i]->name, name) == 0)\n\t\t\tbreak;\n\n\treturn compressor[i];\n}\n\nstruct compressor *lookup_compressor_id(int id) {\n\tint i;\n\n\tfor (i = 0; compressor[i]->id; i++)\n\t\tif (id == compressor[i]->id)\n\t\t\tbreak;\n\n\treturn compressor[i];\n}\n\nvoid display_compressors(char *indent, char *def_comp) {\n\tint i;\n\n\tfor (i = 0; compressor[i]->id; i++)\n\t\tif (compressor[i]->supported)\n\t\t\tfprintf(stderr, \"%s\\t%s%s\\n\", indent, compressor[i]->name, strcmp(compressor[i]->name, def_comp) == 0 ? \" (default)\" : \"\");\n}\n\nvoid display_compressor_usage(char *def_comp) {\n\tint i;\n\n\tfor (i = 0; compressor[i]->id; i++)\n\t\tif (compressor[i]->supported) {\n\t\t\tchar *str = strcmp(compressor[i]->name, def_comp) == 0 ? \" (default)\" : \"\";\n\t\t\tif (compressor[i]->usage) {\n\t\t\t\tfprintf(stderr, \"\\t%s%s\\n\", compressor[i]->name, str);\n\t\t\t\tcompressor[i]->usage();\n\t\t\t} else\n\t\t\t\tfprintf(stderr, \"\\t%s (no options)%s\\n\", compressor[i]->name, str);\n\t\t}\n}\n"
  },
  {
    "path": "src/squashfs/gzip_wrapper.c",
    "content": "/*\n * Copyright (c) 2009, 2010, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * gzip_wrapper.c\n *\n * Support for ZLIB compression http://www.zlib.net\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <zlib.h>\n\n#include \"squashfs_fs.h\"\n#include \"gzip_wrapper.h\"\n#include \"compressor.h\"\n\nstatic struct strategy strategy[] = {\n\t{\"default\", Z_DEFAULT_STRATEGY, 0},\n\t{\"filtered\", Z_FILTERED, 0},\n\t{\"huffman_only\", Z_HUFFMAN_ONLY, 0},\n\t{\"run_length_encoded\", Z_RLE, 0},\n\t{\"fixed\", Z_FIXED, 0},\n\t{NULL, 0, 0}\n};\n\nstatic int strategy_count = 0;\n\n/* default compression level */\nstatic int compression_level = GZIP_DEFAULT_COMPRESSION_LEVEL;\n\n/* default window size */\nstatic int window_size = GZIP_DEFAULT_WINDOW_SIZE;\n\n/*\n * This function is called by the options parsing code in mksquashfs.c\n * to parse any -X compressor option.\n *\n * This function returns:\n *\t>=0 (number of additional args parsed) on success\n *\t-1 if the option was unrecognised, or\n *\t-2 if the option was recognised, but otherwise bad in\n *\t   some way (e.g. invalid parameter)\n *\n * Note: this function sets internal compressor state, but does not\n * pass back the results of the parsing other than success/failure.\n * The gzip_dump_options() function is called later to get the options in\n * a format suitable for writing to the filesystem.\n */\nstatic int gzip_options(char *argv[], int argc) {\n\tif (strcmp(argv[0], \"-Xcompression-level\") == 0) {\n\t\tif (argc < 2) {\n\t\t\tfprintf(stderr, \"gzip: -Xcompression-level missing \" \"compression level\\n\");\n\t\t\tfprintf(stderr, \"gzip: -Xcompression-level it \" \"should be 1 >= n <= 9\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\tcompression_level = atoi(argv[1]);\n\t\tif (compression_level < 1 || compression_level > 9) {\n\t\t\tfprintf(stderr, \"gzip: -Xcompression-level invalid, it \" \"should be 1 >= n <= 9\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\treturn 1;\n\t} else if (strcmp(argv[0], \"-Xwindow-size\") == 0) {\n\t\tif (argc < 2) {\n\t\t\tfprintf(stderr, \"gzip: -Xwindow-size missing window \" \"\tsize\\n\");\n\t\t\tfprintf(stderr, \"gzip: -Xwindow-size <window-size>\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\twindow_size = atoi(argv[1]);\n\t\tif (window_size < 8 || window_size > 15) {\n\t\t\tfprintf(stderr, \"gzip: -Xwindow-size invalid, it \" \"should be 8 >= n <= 15\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\treturn 1;\n\t} else if (strcmp(argv[0], \"-Xstrategy\") == 0) {\n\t\tchar *name;\n\t\tint i;\n\n\t\tif (argc < 2) {\n\t\t\tfprintf(stderr, \"gzip: -Xstrategy missing \" \"strategies\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\tname = argv[1];\n\t\twhile (name[0] != '\\0') {\n\t\t\tfor (i = 0; strategy[i].name; i++) {\n\t\t\t\tint n = strlen(strategy[i].name);\n\t\t\t\tif ((strncmp(name, strategy[i].name, n) == 0) && (name[n] == '\\0' || name[n] == ',')) {\n\t\t\t\t\tif (strategy[i].selected == 0) {\n\t\t\t\t\t\tstrategy[i].selected = 1;\n\t\t\t\t\t\tstrategy_count++;\n\t\t\t\t\t}\n\t\t\t\t\tname += name[n] == ',' ? n + 1 : n;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (strategy[i].name == NULL) {\n\t\t\t\tfprintf(stderr, \"gzip: -Xstrategy unrecognised \" \"strategy\\n\");\n\t\t\t\tgoto failed;\n\t\t\t}\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\treturn -1;\n\n failed:\n\treturn -2;\n}\n\n/*\n * This function is called after all options have been parsed.\n * It is used to do post-processing on the compressor options using\n * values that were not expected to be known at option parse time.\n *\n * This function returns 0 on successful post processing, or\n *\t\t\t-1 on error\n */\nstatic int gzip_options_post(int block_size) {\n\tif (strategy_count == 1 && strategy[0].selected) {\n\t\tstrategy_count = 0;\n\t\tstrategy[0].selected = 0;\n\t}\n\n\treturn 0;\n}\n\n/*\n * This function is called by mksquashfs to dump the parsed\n * compressor options in a format suitable for writing to the\n * compressor options field in the filesystem (stored immediately\n * after the superblock).\n *\n * This function returns a pointer to the compression options structure\n * to be stored (and the size), or NULL if there are no compression\n * options\n *\n */\nstatic void *gzip_dump_options(int block_size, int *size) {\n\tstatic struct gzip_comp_opts comp_opts;\n\tint i, strategies = 0;\n\n\t/*\n\t * If default compression options of:\n\t * compression-level: 8 and\n\t * window-size: 15 and\n\t * strategy_count == 0 then\n\t * don't store a compression options structure (this is compatible\n\t * with the legacy implementation of GZIP for Squashfs)\n\t */\n\tif (compression_level == GZIP_DEFAULT_COMPRESSION_LEVEL && window_size == GZIP_DEFAULT_WINDOW_SIZE && strategy_count == 0)\n\t\treturn NULL;\n\n\tfor (i = 0; strategy[i].name; i++)\n\t\tstrategies |= strategy[i].selected << i;\n\n\tcomp_opts.compression_level = compression_level;\n\tcomp_opts.window_size = window_size;\n\tcomp_opts.strategy = strategies;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(&comp_opts);\n\n\t*size = sizeof(comp_opts);\n\treturn &comp_opts;\n}\n\n/*\n * This function is a helper specifically for the append mode of\n * mksquashfs.  Its purpose is to set the internal compressor state\n * to the stored compressor options in the passed compressor options\n * structure.\n *\n * In effect this function sets up the compressor options\n * to the same state they were when the filesystem was originally\n * generated, this is to ensure on appending, the compressor uses\n * the same compression options that were used to generate the\n * original filesystem.\n *\n * Note, even if there are no compressor options, this function is still\n * called with an empty compressor structure (size == 0), to explicitly\n * set the default options, this is to ensure any user supplied\n * -X options on the appending mksquashfs command line are over-ridden\n *\n * This function returns 0 on sucessful extraction of options, and\n *\t\t\t-1 on error\n */\nstatic int gzip_extract_options(int block_size, void *buffer, int size) {\n\tstruct gzip_comp_opts *comp_opts = buffer;\n\tint i;\n\n\tif (size == 0) {\n\t\t/* Set default values */\n\t\tcompression_level = GZIP_DEFAULT_COMPRESSION_LEVEL;\n\t\twindow_size = GZIP_DEFAULT_WINDOW_SIZE;\n\t\tstrategy_count = 0;\n\t\treturn 0;\n\t}\n\n\t/* we expect a comp_opts structure of sufficient size to be present */\n\tif (size < sizeof(*comp_opts))\n\t\tgoto failed;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(comp_opts);\n\n\t/* Check comp_opts structure for correctness */\n\tif (comp_opts->compression_level < 1 || comp_opts->compression_level > 9) {\n\t\tfprintf(stderr, \"gzip: bad compression level in \" \"compression options structure\\n\");\n\t\tgoto failed;\n\t}\n\tcompression_level = comp_opts->compression_level;\n\n\tif (comp_opts->window_size < 8 || comp_opts->window_size > 15) {\n\t\tfprintf(stderr, \"gzip: bad window size in \" \"compression options structure\\n\");\n\t\tgoto failed;\n\t}\n\twindow_size = comp_opts->window_size;\n\n\tstrategy_count = 0;\n\tfor (i = 0; strategy[i].name; i++) {\n\t\tif ((comp_opts->strategy >> i) & 1) {\n\t\t\tstrategy[i].selected = 1;\n\t\t\tstrategy_count++;\n\t\t} else\n\t\t\tstrategy[i].selected = 0;\n\t}\n\n\treturn 0;\n\n failed:\n\tfprintf(stderr, \"gzip: error reading stored compressor options from \" \"filesystem!\\n\");\n\n\treturn -1;\n}\n\nvoid gzip_display_options(void *buffer, int size) {\n\tstruct gzip_comp_opts *comp_opts = buffer;\n\tint i, printed;\n\n\t/* we expect a comp_opts structure of sufficient size to be present */\n\tif (size < sizeof(*comp_opts))\n\t\tgoto failed;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(comp_opts);\n\n\t/* Check comp_opts structure for correctness */\n\tif (comp_opts->compression_level < 1 || comp_opts->compression_level > 9) {\n\t\tfprintf(stderr, \"gzip: bad compression level in \" \"compression options structure\\n\");\n\t\tgoto failed;\n\t}\n\tprintf(\"\\tcompression-level %d\\n\", comp_opts->compression_level);\n\n\tif (comp_opts->window_size < 8 || comp_opts->window_size > 15) {\n\t\tfprintf(stderr, \"gzip: bad window size in \" \"compression options structure\\n\");\n\t\tgoto failed;\n\t}\n\tprintf(\"\\twindow-size %d\\n\", comp_opts->window_size);\n\n\tfor (i = 0, printed = 0; strategy[i].name; i++) {\n\t\tif ((comp_opts->strategy >> i) & 1) {\n\t\t\tif (printed)\n\t\t\t\tprintf(\", \");\n\t\t\telse\n\t\t\t\tprintf(\"\\tStrategies selected: \");\n\t\t\tprintf(\"%s\", strategy[i].name);\n\t\t\tprinted = 1;\n\t\t}\n\t}\n\n\tif (!printed)\n\t\tprintf(\"\\tStrategies selected: default\\n\");\n\telse\n\t\tprintf(\"\\n\");\n\n\treturn;\n\n failed:\n\tfprintf(stderr, \"gzip: error reading stored compressor options from \" \"filesystem!\\n\");\n}\n\n/*\n * This function is called by mksquashfs to initialise the\n * compressor, before compress() is called.\n *\n * This function returns 0 on success, and\n *\t\t\t-1 on error\n */\nstatic int gzip_init(void **strm, int block_size, int datablock) {\n\tint i, j, res;\n\tstruct gzip_stream *stream;\n\n\tif (!datablock || !strategy_count) {\n\t\tstream = malloc(sizeof(*stream) + sizeof(struct gzip_strategy));\n\t\tif (stream == NULL)\n\t\t\tgoto failed;\n\n\t\tstream->strategies = 1;\n\t\tstream->strategy[0].strategy = Z_DEFAULT_STRATEGY;\n\t} else {\n\t\tstream = malloc(sizeof(*stream) + sizeof(struct gzip_strategy) * strategy_count);\n\t\tif (stream == NULL)\n\t\t\tgoto failed;\n\n\t\tmemset(stream->strategy, 0, sizeof(struct gzip_strategy) * strategy_count);\n\n\t\tstream->strategies = strategy_count;\n\n\t\tfor (i = 0, j = 0; strategy[i].name; i++) {\n\t\t\tif (!strategy[i].selected)\n\t\t\t\tcontinue;\n\n\t\t\tstream->strategy[j].strategy = strategy[i].strategy;\n\t\t\tif (j) {\n\t\t\t\tstream->strategy[j].buffer = malloc(block_size);\n\t\t\t\tif (stream->strategy[j].buffer == NULL)\n\t\t\t\t\tgoto failed2;\n\t\t\t}\n\t\t\tj++;\n\t\t}\n\t}\n\n\tstream->stream.zalloc = Z_NULL;\n\tstream->stream.zfree = Z_NULL;\n\tstream->stream.opaque = 0;\n\n\tres = deflateInit2(&stream->stream, compression_level, Z_DEFLATED, window_size, 8, stream->strategy[0].strategy);\n\tif (res != Z_OK)\n\t\tgoto failed2;\n\n\t*strm = stream;\n\treturn 0;\n\n failed2:\n\tfor (i = 1; i < stream->strategies; i++)\n\t\tfree(stream->strategy[i].buffer);\n\tfree(stream);\n failed:\n\treturn -1;\n}\n\nstatic int gzip_compress(void *strm, void *d, void *s, int size, int block_size, int *error) {\n\tint i, res;\n\tstruct gzip_stream *stream = strm;\n\tstruct gzip_strategy *selected = NULL;\n\n\tstream->strategy[0].buffer = d;\n\n\tfor (i = 0; i < stream->strategies; i++) {\n\t\tstruct gzip_strategy *strategy = &stream->strategy[i];\n\n\t\tres = deflateReset(&stream->stream);\n\t\tif (res != Z_OK)\n\t\t\tgoto failed;\n\n\t\tstream->stream.next_in = s;\n\t\tstream->stream.avail_in = size;\n\t\tstream->stream.next_out = strategy->buffer;\n\t\tstream->stream.avail_out = block_size;\n\n\t\tif (stream->strategies > 1) {\n\t\t\tres = deflateParams(&stream->stream, compression_level, strategy->strategy);\n\t\t\tif (res != Z_OK)\n\t\t\t\tgoto failed;\n\t\t}\n\n\t\tres = deflate(&stream->stream, Z_FINISH);\n\t\tstrategy->length = stream->stream.total_out;\n\t\tif (res == Z_STREAM_END) {\n\t\t\tif (!selected || selected->length > strategy->length)\n\t\t\t\tselected = strategy;\n\t\t} else if (res != Z_OK)\n\t\t\tgoto failed;\n\t}\n\n\tif (!selected)\n\t\t/*\n\t\t * Output buffer overflow.  Return out of buffer space\n\t\t */\n\t\treturn 0;\n\n\tif (selected->buffer != d)\n\t\tmemcpy(d, selected->buffer, selected->length);\n\n\treturn (int)selected->length;\n\n failed:\n\t/*\n\t * All other errors return failure, with the compressor\n\t * specific error code in *error\n\t */\n\t*error = res;\n\treturn -1;\n}\n\nstatic int gzip_uncompress(void *d, void *s, int size, int outsize, int *error) {\n\tint res;\n\tunsigned long bytes = outsize;\n\n\tres = uncompress(d, &bytes, s, size);\n\n\tif (res == Z_OK)\n\t\treturn (int)bytes;\n\telse {\n\t\t*error = res;\n\t\treturn -1;\n\t}\n}\n\nvoid gzip_usage() {\n\tfprintf(stderr, \"\\t  -Xcompression-level <compression-level>\\n\");\n\tfprintf(stderr, \"\\t\\t<compression-level> should be 1 .. 9 (default \" \"%d)\\n\", GZIP_DEFAULT_COMPRESSION_LEVEL);\n\tfprintf(stderr, \"\\t  -Xwindow-size <window-size>\\n\");\n\tfprintf(stderr, \"\\t\\t<window-size> should be 8 .. 15 (default \" \"%d)\\n\", GZIP_DEFAULT_WINDOW_SIZE);\n\tfprintf(stderr, \"\\t  -Xstrategy strategy1,strategy2,...,strategyN\\n\");\n\tfprintf(stderr, \"\\t\\tCompress using strategy1,strategy2,...,strategyN\" \" in turn\\n\");\n\tfprintf(stderr, \"\\t\\tand choose the best compression.\\n\");\n\tfprintf(stderr, \"\\t\\tAvailable strategies: default, filtered, \" \"huffman_only,\\n\\t\\trun_length_encoded and fixed\\n\");\n}\n\nstruct compressor gzip_comp_ops = {\n\t.init = gzip_init,\n\t.compress = gzip_compress,\n\t.uncompress = gzip_uncompress,\n\t.options = gzip_options,\n\t.options_post = gzip_options_post,\n\t.dump_options = gzip_dump_options,\n\t.extract_options = gzip_extract_options,\n\t.display_options = gzip_display_options,\n\t.usage = gzip_usage,\n\t.id = ZLIB_COMPRESSION,\n\t.name = \"gzip\",\n\t.supported = 1\n};\n"
  },
  {
    "path": "src/squashfs/info.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * info.c\n */\n\n#include <pthread.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include <signal.h>\n#include <sys/time.h>\n#include <stdio.h>\n#include <math.h>\n#include <stdarg.h>\n#include <errno.h>\n#include <stdlib.h>\n#include <dirent.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <string.h>\n\n#include \"squashfs_fs.h\"\n#include \"mksquashfs.h\"\n#include \"error.h\"\n#include \"progressbar.h\"\n#include \"caches-queues-lists.h\"\n\nstatic int silent = 0;\nstatic struct dir_ent *ent = NULL;\n\npthread_t info_thread;\n\nvoid disable_info() {\n\tent = NULL;\n}\n\nvoid update_info(struct dir_ent *dir_ent) {\n\tent = dir_ent;\n}\n\nvoid print_filename() {\n\tstruct dir_ent *dir_ent = ent;\n\n\tif (dir_ent == NULL)\n\t\treturn;\n\n\tif (dir_ent->our_dir->subpath[0] != '\\0')\n\t\tINFO(\"%s/%s\\n\", dir_ent->our_dir->subpath, dir_ent->name);\n\telse\n\t\tINFO(\"/%s\\n\", dir_ent->name);\n}\n\nvoid dump_state() {\n\tdisable_progress_bar();\n\n\tprintf(\"Queue and Cache status dump\\n\");\n\tprintf(\"===========================\\n\");\n\n\tprintf(\"file buffer queue (reader thread -> deflate thread(s))\\n\");\n\tdump_queue(to_deflate);\n\n\tprintf(\"uncompressed fragment queue (reader thread -> fragment\" \" thread(s))\\n\");\n\tdump_queue(to_process_frag);\n\n\tprintf(\"processed fragment queue (fragment thread(s) -> main\" \" thread)\\n\");\n\tdump_seq_queue(to_main, 1);\n\n\tprintf(\"compressed block queue (deflate thread(s) -> main thread)\\n\");\n\tdump_seq_queue(to_main, 0);\n\n\tprintf(\"uncompressed packed fragment queue (main thread -> fragment\" \" deflate thread(s))\\n\");\n\tdump_queue(to_frag);\n\n\tprintf(\"locked frag queue (compressed frags waiting while multi-block\" \" file is written)\\n\");\n\tdump_queue(locked_fragment);\n\n\tprintf(\"compressed block queue (main & fragment deflate threads(s) ->\" \" writer thread)\\n\");\n\tdump_queue(to_writer);\n\n\tprintf(\"read cache (uncompressed blocks read by reader thread)\\n\");\n\tdump_cache(reader_buffer);\n\n\tprintf(\"block write cache (compressed blocks waiting for the writer\" \" thread)\\n\");\n\tdump_cache(bwriter_buffer);\n\tprintf(\"fragment write cache (compressed fragments waiting for the\" \" writer thread)\\n\");\n\tdump_cache(fwriter_buffer);\n\n\tprintf(\"fragment cache (frags waiting to be compressed by fragment\" \" deflate thread(s))\\n\");\n\tdump_cache(fragment_buffer);\n\n\tprintf(\"fragment reserve cache (avoids pipeline stall if frag cache\" \" full in dup check)\\n\");\n\tdump_cache(reserve_cache);\n\n\tenable_progress_bar();\n}\n\nvoid *info_thrd(void *arg) {\n\tsigset_t sigmask;\n\tstruct timespec timespec = {.tv_sec = 1,.tv_nsec = 0 };\n\tint sig, waiting = 0;\n\n\tsigemptyset(&sigmask);\n\tsigaddset(&sigmask, SIGQUIT);\n\tsigaddset(&sigmask, SIGHUP);\n\n\twhile (1) {\n\t\tif (waiting)\n\t\t\tsig = sigtimedwait(&sigmask, NULL, &timespec);\n\t\telse\n\t\t\tsig = sigwaitinfo(&sigmask, NULL);\n\n\t\tif (sig == -1) {\n\t\t\tswitch (errno) {\n\t\t\tcase EAGAIN:\n\t\t\t\t/* interval timed out */\n\t\t\t\twaiting = 0;\n\t\t\t\t/* FALLTHROUGH */\n\t\t\tcase EINTR:\n\t\t\t\t/* if waiting, the wait will be longer, but\n\t\t\t\t   that's OK */\n\t\t\t\tcontinue;\n\t\t\tdefault:\n\t\t\t\tBAD_ERROR(\"sigtimedwait/sigwaitinfo failed \" \"because %s\\n\", strerror(errno));\n\t\t\t}\n\t\t}\n\n\t\tif (sig == SIGQUIT && !waiting) {\n\t\t\tprint_filename();\n\n\t\t\t/* set one second interval period, if ^\\ received\n\t\t\t   within then, dump queue and cache status */\n\t\t\twaiting = 1;\n\t\t} else\n\t\t\tdump_state();\n\t}\n}\n\nvoid init_info() {\n\tpthread_create(&info_thread, NULL, info_thrd, NULL);\n}\n"
  },
  {
    "path": "src/squashfs/lz4_wrapper.c",
    "content": "/*\n * Copyright (c) 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * lz4_wrapper.c\n *\n * Support for LZ4 compression http://fastcompression.blogspot.com/p/lz4.html\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <lz4.h>\n#include <lz4hc.h>\n\n#include \"squashfs_fs.h\"\n#include \"lz4_wrapper.h\"\n#include \"compressor.h\"\n\nstatic int hc = 0;\n\n/*\n * This function is called by the options parsing code in mksquashfs.c\n * to parse any -X compressor option.\n *\n * This function returns:\n *\t>=0 (number of additional args parsed) on success\n *\t-1 if the option was unrecognised, or\n *\t-2 if the option was recognised, but otherwise bad in\n *\t   some way (e.g. invalid parameter)\n *\n * Note: this function sets internal compressor state, but does not\n * pass back the results of the parsing other than success/failure.\n * The lz4_dump_options() function is called later to get the options in\n * a format suitable for writing to the filesystem.\n */\nstatic int lz4_options(char *argv[], int argc) {\n\tif (strcmp(argv[0], \"-Xhc\") == 0) {\n\t\thc = 1;\n\t\treturn 0;\n\t}\n\n\treturn -1;\n}\n\n/*\n * This function is called by mksquashfs to dump the parsed\n * compressor options in a format suitable for writing to the\n * compressor options field in the filesystem (stored immediately\n * after the superblock).\n *\n * This function returns a pointer to the compression options structure\n * to be stored (and the size), or NULL if there are no compression\n * options\n *\n * Currently LZ4 always returns a comp_opts structure, with\n * the version indicating LZ4_LEGACY stream fomat.  This is to\n * easily accomodate changes in the kernel code to different\n * stream formats\n */\nstatic void *lz4_dump_options(int block_size, int *size) {\n\tstatic struct lz4_comp_opts comp_opts;\n\n\tcomp_opts.version = LZ4_LEGACY;\n\tcomp_opts.flags = hc ? LZ4_HC : 0;\n\tSQUASHFS_INSWAP_COMP_OPTS(&comp_opts);\n\n\t*size = sizeof(comp_opts);\n\treturn &comp_opts;\n}\n\n/*\n * This function is a helper specifically for the append mode of\n * mksquashfs.  Its purpose is to set the internal compressor state\n * to the stored compressor options in the passed compressor options\n * structure.\n *\n * In effect this function sets up the compressor options\n * to the same state they were when the filesystem was originally\n * generated, this is to ensure on appending, the compressor uses\n * the same compression options that were used to generate the\n * original filesystem.\n *\n * Note, even if there are no compressor options, this function is still\n * called with an empty compressor structure (size == 0), to explicitly\n * set the default options, this is to ensure any user supplied\n * -X options on the appending mksquashfs command line are over-ridden\n *\n * This function returns 0 on sucessful extraction of options, and\n *\t\t\t-1 on error\n */\nstatic int lz4_extract_options(int block_size, void *buffer, int size) {\n\tstruct lz4_comp_opts *comp_opts = buffer;\n\n\t/* we expect a comp_opts structure to be present */\n\tif (size < sizeof(*comp_opts))\n\t\tgoto failed;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(comp_opts);\n\n\t/* we expect the stream format to be LZ4_LEGACY */\n\tif (comp_opts->version != LZ4_LEGACY) {\n\t\tfprintf(stderr, \"lz4: unknown LZ4 version\\n\");\n\t\tgoto failed;\n\t}\n\n\t/*\n\t * Check compression flags, currently only LZ4_HC (\"high compression\")\n\t * can be set.\n\t */\n\tif (comp_opts->flags == LZ4_HC)\n\t\thc = 1;\n\telse if (comp_opts->flags != 0) {\n\t\tfprintf(stderr, \"lz4: unknown LZ4 flags\\n\");\n\t\tgoto failed;\n\t}\n\n\treturn 0;\n\n failed:\n\tfprintf(stderr, \"lz4: error reading stored compressor options from \" \"filesystem!\\n\");\n\n\treturn -1;\n}\n\n/*\n * This function is a helper specifically for unsquashfs.\n * Its purpose is to check that the compression options are\n * understood by this version of LZ4.\n *\n * This is important for LZ4 because the format understood by the\n * Linux kernel may change from the already obsolete legacy format\n * currently supported.\n *\n * If this does happen, then this version of LZ4 will not be able to decode\n * the newer format.  So we need to check for this.\n *\n * This function returns 0 on sucessful checking of options, and\n *\t\t\t-1 on error\n */\nstatic int lz4_check_options(int block_size, void *buffer, int size) {\n\tstruct lz4_comp_opts *comp_opts = buffer;\n\n\t/* we expect a comp_opts structure to be present */\n\tif (size < sizeof(*comp_opts))\n\t\tgoto failed;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(comp_opts);\n\n\t/* we expect the stream format to be LZ4_LEGACY */\n\tif (comp_opts->version != LZ4_LEGACY) {\n\t\tfprintf(stderr, \"lz4: unknown LZ4 version\\n\");\n\t\tgoto failed;\n\t}\n\n\treturn 0;\n\n failed:\n\tfprintf(stderr, \"lz4: error reading stored compressor options from \" \"filesystem!\\n\");\n\treturn -1;\n}\n\nvoid lz4_display_options(void *buffer, int size) {\n\tstruct lz4_comp_opts *comp_opts = buffer;\n\n\t/* check passed comp opts struct is of the correct length */\n\tif (size < sizeof(*comp_opts))\n\t\tgoto failed;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(comp_opts);\n\n\t/* we expect the stream format to be LZ4_LEGACY */\n\tif (comp_opts->version != LZ4_LEGACY) {\n\t\tfprintf(stderr, \"lz4: unknown LZ4 version\\n\");\n\t\tgoto failed;\n\t}\n\n\t/*\n\t * Check compression flags, currently only LZ4_HC (\"high compression\")\n\t * can be set.\n\t */\n\tif (comp_opts->flags & ~LZ4_FLAGS_MASK) {\n\t\tfprintf(stderr, \"lz4: unknown LZ4 flags\\n\");\n\t\tgoto failed;\n\t}\n\n\tif (comp_opts->flags & LZ4_HC)\n\t\tprintf(\"\\tHigh Compression option specified (-Xhc)\\n\");\n\n\treturn;\n\n failed:\n\tfprintf(stderr, \"lz4: error reading stored compressor options from \" \"filesystem!\\n\");\n}\n\nstatic int lz4_compress(void *strm, void *dest, void *src, int size, int block_size, int *error) {\n\tint res;\n\n\tif (hc)\n\t\tres = LZ4_compressHC_limitedOutput(src, dest, size, block_size);\n\telse\n\t\tres = LZ4_compress_limitedOutput(src, dest, size, block_size);\n\n\tif (res == 0) {\n\t\t/*\n\t\t * Output buffer overflow.  Return out of buffer space\n\t\t */\n\t\treturn 0;\n\t} else if (res < 0) {\n\t\t/*\n\t\t * All other errors return failure, with the compressor\n\t\t * specific error code in *error\n\t\t */\n\t\t*error = res;\n\t\treturn -1;\n\t}\n\n\treturn res;\n}\n\nstatic int lz4_uncompress(void *dest, void *src, int size, int outsize, int *error) {\n\tint res = LZ4_decompress_safe(src, dest, size, outsize);\n\tif (res < 0) {\n\t\t*error = res;\n\t\treturn -1;\n\t}\n\n\treturn res;\n}\n\nvoid lz4_usage() {\n\tfprintf(stderr, \"\\t  -Xhc\\n\");\n\tfprintf(stderr, \"\\t\\tCompress using LZ4 High Compression\\n\");\n}\n\nstruct compressor lz4_comp_ops = {\n\t.compress = lz4_compress,\n\t.uncompress = lz4_uncompress,\n\t.options = lz4_options,\n\t.dump_options = lz4_dump_options,\n\t.extract_options = lz4_extract_options,\n\t.check_options = lz4_check_options,\n\t.display_options = lz4_display_options,\n\t.usage = lz4_usage,\n\t.id = LZ4_COMPRESSION,\n\t.name = \"lz4\",\n\t.supported = 1\n};\n"
  },
  {
    "path": "src/squashfs/lzma_wrapper.c",
    "content": "/*\n * Copyright (c) 2009, 2010, 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * lzma_wrapper.c\n *\n * Support for LZMA1 compression using LZMA SDK (4.65 used in\n * development, other versions may work) http://www.7-zip.org/sdk.html\n */\n\n#include <LzmaLib.h>\n\n#include \"squashfs_fs.h\"\n#include \"compressor.h\"\n\n#define LZMA_HEADER_SIZE\t(LZMA_PROPS_SIZE + 8)\n\nstatic int lzma_compress(void *strm, void *dest, void *src, int size, int block_size, int *error) {\n\tunsigned char *d = dest;\n\tsize_t props_size = LZMA_PROPS_SIZE, outlen = block_size - LZMA_HEADER_SIZE;\n\tint res;\n\n\tres = LzmaCompress(dest + LZMA_HEADER_SIZE, &outlen, src, size, dest, &props_size, 5, block_size, 3, 0, 2, 32, 1);\n\n\tif (res == SZ_ERROR_OUTPUT_EOF) {\n\t\t/*\n\t\t * Output buffer overflow.  Return out of buffer space error\n\t\t */\n\t\treturn 0;\n\t}\n\n\tif (res != SZ_OK) {\n\t\t/*\n\t\t * All other errors return failure, with the compressor\n\t\t * specific error code in *error\n\t\t */\n\t\t*error = res;\n\t\treturn -1;\n\t}\n\n\t/*\n\t * Fill in the 8 byte little endian uncompressed size field in the\n\t * LZMA header.  8 bytes is excessively large for squashfs but\n\t * this is the standard LZMA header and which is expected by the kernel\n\t * code\n\t */\n\td[LZMA_PROPS_SIZE] = size & 255;\n\td[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;\n\td[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;\n\td[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;\n\td[LZMA_PROPS_SIZE + 4] = 0;\n\td[LZMA_PROPS_SIZE + 5] = 0;\n\td[LZMA_PROPS_SIZE + 6] = 0;\n\td[LZMA_PROPS_SIZE + 7] = 0;\n\n\t/*\n\t * Success, return the compressed size.  Outlen returned by the LZMA\n\t * compressor does not include the LZMA header space\n\t */\n\treturn outlen + LZMA_HEADER_SIZE;\n}\n\nstatic int lzma_uncompress(void *dest, void *src, int size, int outsize, int *error) {\n\tunsigned char *s = src;\n\tsize_t outlen, inlen = size - LZMA_HEADER_SIZE;\n\tint res;\n\n\toutlen = s[LZMA_PROPS_SIZE] | (s[LZMA_PROPS_SIZE + 1] << 8) | (s[LZMA_PROPS_SIZE + 2] << 16) | (s[LZMA_PROPS_SIZE + 3] << 24);\n\n\tif (outlen > outsize) {\n\t\t*error = 0;\n\t\treturn -1;\n\t}\n\n\tres = LzmaUncompress(dest, &outlen, src + LZMA_HEADER_SIZE, &inlen, src, LZMA_PROPS_SIZE);\n\n\tif (res == SZ_OK)\n\t\treturn outlen;\n\telse {\n\t\t*error = res;\n\t\treturn -1;\n\t}\n}\n\nstruct compressor lzma_comp_ops = {\n\t.init = NULL,\n\t.compress = lzma_compress,\n\t.uncompress = lzma_uncompress,\n\t.options = NULL,\n\t.usage = NULL,\n\t.id = LZMA_COMPRESSION,\n\t.name = \"lzma\",\n\t.supported = 1\n};\n"
  },
  {
    "path": "src/squashfs/lzma_xz_wrapper.c",
    "content": "/*\n * Copyright (c) 2010, 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * lzma_xz_wrapper.c\n *\n * Support for LZMA1 compression using XZ Utils liblzma http://tukaani.org/xz/\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <lzma.h>\n\n#include \"squashfs_fs.h\"\n#include \"compressor.h\"\n\n#define LZMA_PROPS_SIZE 5\n#define LZMA_UNCOMP_SIZE 8\n#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE)\n\n#define LZMA_OPTIONS 5\n#define MEMLIMIT (32 * 1024 * 1024)\n\nstatic int lzma_compress(void *dummy, void *dest, void *src, int size, int block_size, int *error) {\n\tunsigned char *d = (unsigned char *)dest;\n\tlzma_options_lzma opt;\n\tlzma_stream strm = LZMA_STREAM_INIT;\n\tint res;\n\n\tlzma_lzma_preset(&opt, LZMA_OPTIONS);\n\topt.dict_size = block_size;\n\n\tres = lzma_alone_encoder(&strm, &opt);\n\tif (res != LZMA_OK) {\n\t\tlzma_end(&strm);\n\t\tgoto failed;\n\t}\n\n\tstrm.next_out = dest;\n\tstrm.avail_out = block_size;\n\tstrm.next_in = src;\n\tstrm.avail_in = size;\n\n\tres = lzma_code(&strm, LZMA_FINISH);\n\tlzma_end(&strm);\n\n\tif (res == LZMA_STREAM_END) {\n\t\t/*\n\t\t * Fill in the 8 byte little endian uncompressed size field in\n\t\t * the LZMA header.  8 bytes is excessively large for squashfs\n\t\t * but this is the standard LZMA header and which is expected by\n\t\t * the kernel code\n\t\t */\n\n\t\td[LZMA_PROPS_SIZE] = size & 255;\n\t\td[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;\n\t\td[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;\n\t\td[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;\n\t\td[LZMA_PROPS_SIZE + 4] = 0;\n\t\td[LZMA_PROPS_SIZE + 5] = 0;\n\t\td[LZMA_PROPS_SIZE + 6] = 0;\n\t\td[LZMA_PROPS_SIZE + 7] = 0;\n\n\t\treturn (int)strm.total_out;\n\t}\n\n\tif (res == LZMA_OK)\n\t\t/*\n\t\t * Output buffer overflow.  Return out of buffer space\n\t\t */\n\t\treturn 0;\n\n failed:\n\t/*\n\t * All other errors return failure, with the compressor\n\t * specific error code in *error\n\t */\n\t*error = res;\n\treturn -1;\n}\n\nstatic int lzma_uncompress(void *dest, void *src, int size, int outsize, int *error) {\n\tlzma_stream strm = LZMA_STREAM_INIT;\n\tint uncompressed_size = 0, res;\n\tunsigned char lzma_header[LZMA_HEADER_SIZE];\n\n\tres = lzma_alone_decoder(&strm, MEMLIMIT);\n\tif (res != LZMA_OK) {\n\t\tlzma_end(&strm);\n\t\tgoto failed;\n\t}\n\n\tmemcpy(lzma_header, src, LZMA_HEADER_SIZE);\n\tuncompressed_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);\n\n\tif (uncompressed_size > outsize) {\n\t\tres = 0;\n\t\tgoto failed;\n\t}\n\n\tmemset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE);\n\n\tstrm.next_out = dest;\n\tstrm.avail_out = outsize;\n\tstrm.next_in = lzma_header;\n\tstrm.avail_in = LZMA_HEADER_SIZE;\n\n\tres = lzma_code(&strm, LZMA_RUN);\n\n\tif (res != LZMA_OK || strm.avail_in != 0) {\n\t\tlzma_end(&strm);\n\t\tgoto failed;\n\t}\n\n\tstrm.next_in = src + LZMA_HEADER_SIZE;\n\tstrm.avail_in = size - LZMA_HEADER_SIZE;\n\n\tres = lzma_code(&strm, LZMA_FINISH);\n\tlzma_end(&strm);\n\n\tif (res == LZMA_STREAM_END || (res == LZMA_OK && strm.total_out >= uncompressed_size && strm.avail_in == 0))\n\t\treturn uncompressed_size;\n\n failed:\n\t*error = res;\n\treturn -1;\n}\n\nstruct compressor lzma_comp_ops = {\n\t.init = NULL,\n\t.compress = lzma_compress,\n\t.uncompress = lzma_uncompress,\n\t.options = NULL,\n\t.usage = NULL,\n\t.id = LZMA_COMPRESSION,\n\t.name = \"lzma\",\n\t.supported = 1\n};\n"
  },
  {
    "path": "src/squashfs/lzo_wrapper.c",
    "content": "/*\n * Copyright (c) 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * lzo_wrapper.c\n *\n * Support for LZO compression http://www.oberhumer.com/opensource/lzo\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <lzo/lzoconf.h>\n#include <lzo/lzo1x.h>\n\n#include \"squashfs_fs.h\"\n#include \"lzo_wrapper.h\"\n#include \"compressor.h\"\n\nstatic struct lzo_algorithm lzo[] = {\n\t{\"lzo1x_1\", LZO1X_1_MEM_COMPRESS, lzo1x_1_compress},\n\t{\"lzo1x_1_11\", LZO1X_1_11_MEM_COMPRESS, lzo1x_1_11_compress},\n\t{\"lzo1x_1_12\", LZO1X_1_12_MEM_COMPRESS, lzo1x_1_12_compress},\n\t{\"lzo1x_1_15\", LZO1X_1_15_MEM_COMPRESS, lzo1x_1_15_compress},\n\t{\"lzo1x_999\", LZO1X_999_MEM_COMPRESS, lzo1x_999_wrapper},\n\t{NULL, 0, NULL}\n};\n\n/* default LZO compression algorithm and compression level */\nstatic int algorithm = SQUASHFS_LZO1X_999;\nstatic int compression_level = SQUASHFS_LZO1X_999_COMP_DEFAULT;\n\n/* user specified compression level */\nstatic int user_comp_level = -1;\n\n/*\n * This function is called by the options parsing code in mksquashfs.c\n * to parse any -X compressor option.\n *\n * This function returns:\n *\t>=0 (number of additional args parsed) on success\n *\t-1 if the option was unrecognised, or\n *\t-2 if the option was recognised, but otherwise bad in\n *\t   some way (e.g. invalid parameter)\n *\n * Note: this function sets internal compressor state, but does not\n * pass back the results of the parsing other than success/failure.\n * The lzo_dump_options() function is called later to get the options in\n * a format suitable for writing to the filesystem.\n */\nstatic int lzo_options(char *argv[], int argc) {\n\tint i;\n\n\tif (strcmp(argv[0], \"-Xalgorithm\") == 0) {\n\t\tif (argc < 2) {\n\t\t\tfprintf(stderr, \"lzo: -Xalgorithm missing algorithm\\n\");\n\t\t\tfprintf(stderr, \"lzo: -Xalgorithm <algorithm>\\n\");\n\t\t\tgoto failed2;\n\t\t}\n\n\t\tfor (i = 0; lzo[i].name; i++) {\n\t\t\tif (strcmp(argv[1], lzo[i].name) == 0) {\n\t\t\t\talgorithm = i;\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\n\t\tfprintf(stderr, \"lzo: -Xalgorithm unrecognised algorithm\\n\");\n\t\tgoto failed2;\n\t} else if (strcmp(argv[0], \"-Xcompression-level\") == 0) {\n\t\tif (argc < 2) {\n\t\t\tfprintf(stderr, \"lzo: -Xcompression-level missing \" \"compression level\\n\");\n\t\t\tfprintf(stderr, \"lzo: -Xcompression-level it \" \"should be 1 >= n <= 9\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\tuser_comp_level = atoi(argv[1]);\n\t\tif (user_comp_level < 1 || user_comp_level > 9) {\n\t\t\tfprintf(stderr, \"lzo: -Xcompression-level invalid, it \" \"should be 1 >= n <= 9\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\treturn -1;\n\n failed:\n\treturn -2;\n\n failed2:\n\tfprintf(stderr, \"lzo: compression algorithm should be one of:\\n\");\n\tfor (i = 0; lzo[i].name; i++)\n\t\tfprintf(stderr, \"\\t%s\\n\", lzo[i].name);\n\treturn -2;\n}\n\n/*\n * This function is called after all options have been parsed.\n * It is used to do post-processing on the compressor options using\n * values that were not expected to be known at option parse time.\n *\n * In this case the LZO algorithm may not be known until after the\n * compression level has been set (-Xalgorithm used after -Xcompression-level)\n *\n * This function returns 0 on successful post processing, or\n *\t\t\t-1 on error\n */\nstatic int lzo_options_post(int block_size) {\n\t/*\n\t * Use of compression level only makes sense for\n\t * LZO1X_999 algorithm\n\t */\n\tif (user_comp_level != -1) {\n\t\tif (algorithm != SQUASHFS_LZO1X_999) {\n\t\t\tfprintf(stderr, \"lzo: -Xcompression-level not \" \"supported by selected %s algorithm\\n\", lzo[algorithm].name);\n\t\t\tfprintf(stderr, \"lzo: -Xcompression-level is only \" \"applicable for the lzo1x_999 algorithm\\n\");\n\t\t\tgoto failed;\n\t\t}\n\t\tcompression_level = user_comp_level;\n\t}\n\n\treturn 0;\n\n failed:\n\treturn -1;\n}\n\n/*\n * This function is called by mksquashfs to dump the parsed\n * compressor options in a format suitable for writing to the\n * compressor options field in the filesystem (stored immediately\n * after the superblock).\n *\n * This function returns a pointer to the compression options structure\n * to be stored (and the size), or NULL if there are no compression\n * options\n *\n */\nstatic void *lzo_dump_options(int block_size, int *size) {\n\tstatic struct lzo_comp_opts comp_opts;\n\n\t/*\n\t * If default compression options of SQUASHFS_LZO1X_999 and\n\t * compression level of SQUASHFS_LZO1X_999_COMP_DEFAULT then\n\t * don't store a compression options structure (this is compatible\n\t * with the legacy implementation of LZO for Squashfs)\n\t */\n\tif (algorithm == SQUASHFS_LZO1X_999 && compression_level == SQUASHFS_LZO1X_999_COMP_DEFAULT)\n\t\treturn NULL;\n\n\tcomp_opts.algorithm = algorithm;\n\tcomp_opts.compression_level = algorithm == SQUASHFS_LZO1X_999 ? compression_level : 0;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(&comp_opts);\n\n\t*size = sizeof(comp_opts);\n\treturn &comp_opts;\n}\n\n/*\n * This function is a helper specifically for the append mode of\n * mksquashfs.  Its purpose is to set the internal compressor state\n * to the stored compressor options in the passed compressor options\n * structure.\n *\n * In effect this function sets up the compressor options\n * to the same state they were when the filesystem was originally\n * generated, this is to ensure on appending, the compressor uses\n * the same compression options that were used to generate the\n * original filesystem.\n *\n * Note, even if there are no compressor options, this function is still\n * called with an empty compressor structure (size == 0), to explicitly\n * set the default options, this is to ensure any user supplied\n * -X options on the appending mksquashfs command line are over-ridden\n *\n * This function returns 0 on sucessful extraction of options, and\n *\t\t\t-1 on error\n */\nstatic int lzo_extract_options(int block_size, void *buffer, int size) {\n\tstruct lzo_comp_opts *comp_opts = buffer;\n\n\tif (size == 0) {\n\t\t/* Set default values */\n\t\talgorithm = SQUASHFS_LZO1X_999;\n\t\tcompression_level = SQUASHFS_LZO1X_999_COMP_DEFAULT;\n\t\treturn 0;\n\t}\n\n\t/* we expect a comp_opts structure of sufficient size to be present */\n\tif (size < sizeof(*comp_opts))\n\t\tgoto failed;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(comp_opts);\n\n\t/* Check comp_opts structure for correctness */\n\tswitch (comp_opts->algorithm) {\n\tcase SQUASHFS_LZO1X_1:\n\tcase SQUASHFS_LZO1X_1_11:\n\tcase SQUASHFS_LZO1X_1_12:\n\tcase SQUASHFS_LZO1X_1_15:\n\t\tif (comp_opts->compression_level != 0) {\n\t\t\tfprintf(stderr, \"lzo: bad compression level in \" \"compression options structure\\n\");\n\t\t\tgoto failed;\n\t\t}\n\t\tbreak;\n\tcase SQUASHFS_LZO1X_999:\n\t\tif (comp_opts->compression_level < 1 || comp_opts->compression_level > 9) {\n\t\t\tfprintf(stderr, \"lzo: bad compression level in \" \"compression options structure\\n\");\n\t\t\tgoto failed;\n\t\t}\n\t\tcompression_level = comp_opts->compression_level;\n\t\tbreak;\n\tdefault:\n\t\tfprintf(stderr, \"lzo: bad algorithm in compression options \" \"structure\\n\");\n\t\tgoto failed;\n\t}\n\n\talgorithm = comp_opts->algorithm;\n\n\treturn 0;\n\n failed:\n\tfprintf(stderr, \"lzo: error reading stored compressor options from \" \"filesystem!\\n\");\n\n\treturn -1;\n}\n\nvoid lzo_display_options(void *buffer, int size) {\n\tstruct lzo_comp_opts *comp_opts = buffer;\n\n\t/* we expect a comp_opts structure of sufficient size to be present */\n\tif (size < sizeof(*comp_opts))\n\t\tgoto failed;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(comp_opts);\n\n\t/* Check comp_opts structure for correctness */\n\tswitch (comp_opts->algorithm) {\n\tcase SQUASHFS_LZO1X_1:\n\tcase SQUASHFS_LZO1X_1_11:\n\tcase SQUASHFS_LZO1X_1_12:\n\tcase SQUASHFS_LZO1X_1_15:\n\t\tprintf(\"\\talgorithm %s\\n\", lzo[comp_opts->algorithm].name);\n\t\tbreak;\n\tcase SQUASHFS_LZO1X_999:\n\t\tif (comp_opts->compression_level < 1 || comp_opts->compression_level > 9) {\n\t\t\tfprintf(stderr, \"lzo: bad compression level in \" \"compression options structure\\n\");\n\t\t\tgoto failed;\n\t\t}\n\t\tprintf(\"\\talgorithm %s\\n\", lzo[comp_opts->algorithm].name);\n\t\tprintf(\"\\tcompression level %d\\n\", comp_opts->compression_level);\n\t\tbreak;\n\tdefault:\n\t\tfprintf(stderr, \"lzo: bad algorithm in compression options \" \"structure\\n\");\n\t\tgoto failed;\n\t}\n\n\treturn;\n\n failed:\n\tfprintf(stderr, \"lzo: error reading stored compressor options from \" \"filesystem!\\n\");\n}\n\n/*\n * This function is called by mksquashfs to initialise the\n * compressor, before compress() is called.\n *\n * This function returns 0 on success, and\n *\t\t\t-1 on error\n */\nstatic int squashfs_lzo_init(void **strm, int block_size, int datablock) {\n\tstruct lzo_stream *stream;\n\n\tstream = *strm = malloc(sizeof(struct lzo_stream));\n\tif (stream == NULL)\n\t\tgoto failed;\n\n\tstream->workspace = malloc(lzo[algorithm].size);\n\tif (stream->workspace == NULL)\n\t\tgoto failed2;\n\n\tstream->buffer = malloc(LZO_MAX_EXPANSION(block_size));\n\tif (stream->buffer != NULL)\n\t\treturn 0;\n\n\tfree(stream->workspace);\n failed2:\n\tfree(stream);\n failed:\n\treturn -1;\n}\n\nstatic int lzo_compress(void *strm, void *dest, void *src, int size, int block_size, int *error) {\n\tint res;\n\tlzo_uint compsize, orig_size = size;\n\tstruct lzo_stream *stream = strm;\n\n\tres = lzo[algorithm].compress(src, size, stream->buffer, &compsize, stream->workspace);\n\tif (res != LZO_E_OK)\n\t\tgoto failed;\n\n\t/* Successful compression, however, we need to check that\n\t * the compressed size is not larger than the available\n\t * buffer space.  Normally in other compressor APIs they take\n\t * a destination buffer size, and overflows return an error.\n\t * With LZO it lacks a destination size and so we must output\n\t * to a temporary buffer large enough to accomodate any\n\t * result, and explictly check here for overflow\n\t */\n\tif (compsize > block_size)\n\t\treturn 0;\n\n\tres = lzo1x_optimize(stream->buffer, compsize, src, &orig_size, NULL);\n\n\tif (res != LZO_E_OK || orig_size != size)\n\t\tgoto failed;\n\n\tmemcpy(dest, stream->buffer, compsize);\n\treturn compsize;\n\n failed:\n\t/* fail, compressor specific error code returned in error */\n\t*error = res;\n\treturn -1;\n}\n\nstatic int lzo_uncompress(void *dest, void *src, int size, int outsize, int *error) {\n\tint res;\n\tlzo_uint outlen = outsize;\n\n\tres = lzo1x_decompress_safe(src, size, dest, &outlen, NULL);\n\tif (res != LZO_E_OK) {\n\t\t*error = res;\n\t\treturn -1;\n\t}\n\n\treturn outlen;\n}\n\nvoid lzo_usage() {\n\tint i;\n\n\tfprintf(stderr, \"\\t  -Xalgorithm <algorithm>\\n\");\n\tfprintf(stderr, \"\\t\\tWhere <algorithm> is one of:\\n\");\n\n\tfor (i = 0; lzo[i].name; i++)\n\t\tfprintf(stderr, \"\\t\\t\\t%s%s\\n\", lzo[i].name, i == SQUASHFS_LZO1X_999 ? \" (default)\" : \"\");\n\n\tfprintf(stderr, \"\\t  -Xcompression-level <compression-level>\\n\");\n\tfprintf(stderr, \"\\t\\t<compression-level> should be 1 .. 9 (default \" \"%d)\\n\", SQUASHFS_LZO1X_999_COMP_DEFAULT);\n\tfprintf(stderr, \"\\t\\tOnly applies to lzo1x_999 algorithm\\n\");\n}\n\n/*\n * Helper function for lzo1x_999 compression algorithm.\n * All other lzo1x_xxx compressors do not take a compression level,\n * so we need to wrap lzo1x_999 to pass the compression level which\n * is applicable to it\n */\nint lzo1x_999_wrapper(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp compsize, lzo_voidp workspace) {\n\treturn lzo1x_999_compress_level(src, src_len, dst, compsize, workspace, NULL, 0, 0, compression_level);\n}\n\nstruct compressor lzo_comp_ops = {\n\t.init = squashfs_lzo_init,\n\t.compress = lzo_compress,\n\t.uncompress = lzo_uncompress,\n\t.options = lzo_options,\n\t.options_post = lzo_options_post,\n\t.dump_options = lzo_dump_options,\n\t.extract_options = lzo_extract_options,\n\t.display_options = lzo_display_options,\n\t.usage = lzo_usage,\n\t.id = LZO_COMPRESSION,\n\t.name = \"lzo\",\n\t.supported = 1\n};\n"
  },
  {
    "path": "src/squashfs/mksquashfs.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,\n * 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * mksquashfs.c\n */\n\n#define FALSE 0\n#define TRUE 1\n#define MAX_LINE 16384\n\n#include <pwd.h>\n#include <grp.h>\n#include <time.h>\n#include <unistd.h>\n#include <stdio.h>\n#include <stddef.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <dirent.h>\n#include <string.h>\n#include <stdlib.h>\n#include <signal.h>\n#include <setjmp.h>\n#include <sys/types.h>\n#include <sys/mman.h>\n#include <pthread.h>\n#include <regex.h>\n#include <fnmatch.h>\n#include <sys/wait.h>\n#include <limits.h>\n#include <ctype.h>\n\n#ifndef linux\n#    define __BYTE_ORDER BYTE_ORDER\n#    define __BIG_ENDIAN BIG_ENDIAN\n#    define __LITTLE_ENDIAN LITTLE_ENDIAN\n#    include <sys/sysctl.h>\n#else\n#    include <endian.h>\n#    include <sys/sysinfo.h>\n#endif\n\n#include \"squashfs_fs.h\"\n#include \"squashfs_swap.h\"\n#include \"mksquashfs.h\"\n#include \"sort.h\"\n#include \"pseudo.h\"\n#include \"compressor.h\"\n#include \"xattr.h\"\n#include \"action.h\"\n#include \"error.h\"\n#include \"progressbar.h\"\n#include \"info.h\"\n#include \"caches-queues-lists.h\"\n#include \"read_fs.h\"\n#include \"restore.h\"\n#include \"process_fragments.h\"\n\nint delete = FALSE;\nint fd;\nstruct squashfs_super_block sBlk;\n\n/* filesystem flags for building */\nint comp_opts = FALSE;\nint no_xattrs = XATTR_DEF;\nint noX = FALSE;\nint duplicate_checking = TRUE;\nint noF = FALSE;\nint no_fragments = FALSE;\nint always_use_fragments = FALSE;\nint noI = FALSE;\nint noD = FALSE;\nint silent = TRUE;\nint exportable = TRUE;\nint sparse_files = TRUE;\nint old_exclude = TRUE;\nint use_regex = FALSE;\nint nopad = FALSE;\nint exit_on_error = FALSE;\n\nlong long global_uid = -1, global_gid = -1;\n\n/* superblock attributes */\nint block_size = SQUASHFS_FILE_SIZE, block_log;\nunsigned int id_count = 0;\nint file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0;\n\n/* write position within data section */\nlong long bytes = 0, total_bytes = 0;\n\n/* in memory directory table - possibly compressed */\nchar *directory_table = NULL;\nunsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0;\n\n/* cached directory table */\nchar *directory_data_cache = NULL;\nunsigned int directory_cache_bytes = 0, directory_cache_size = 0;\n\n/* in memory inode table - possibly compressed */\nchar *inode_table = NULL;\nunsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0;\n\n/* cached inode table */\nchar *data_cache = NULL;\nunsigned int cache_bytes = 0, cache_size = 0, inode_count = 0;\n\n/* inode lookup table */\nsquashfs_inode *inode_lookup_table = NULL;\n\n/* in memory directory data */\n#define I_COUNT_SIZE\t\t128\n#define DIR_ENTRIES\t\t32\n#define INODE_HASH_SIZE\t\t65536\n#define INODE_HASH_MASK\t\t(INODE_HASH_SIZE - 1)\n#define INODE_HASH(dev, ino)\t(ino & INODE_HASH_MASK)\n\nstruct cached_dir_index {\n\tstruct squashfs_dir_index index;\n\tchar *name;\n};\n\nstruct directory {\n\tunsigned int start_block;\n\tunsigned int size;\n\tunsigned char *buff;\n\tunsigned char *p;\n\tunsigned int entry_count;\n\tunsigned char *entry_count_p;\n\tunsigned int i_count;\n\tunsigned int i_size;\n\tstruct cached_dir_index *index;\n\tunsigned char *index_count_p;\n\tunsigned int inode_number;\n};\n\nstruct inode_info *inode_info[INODE_HASH_SIZE];\n\n/* hash tables used to do fast duplicate searches in duplicate check */\nstruct file_info *dupl[65536];\nint dup_files = 0;\n\n/* exclude file handling */\n/* list of exclude dirs/files */\nstruct exclude_info {\n\tdev_t st_dev;\n\tino_t st_ino;\n};\n\n#define EXCLUDE_SIZE 8192\nint exclude = 0;\nstruct exclude_info *exclude_paths = NULL;\nint old_excluded(char *filename, struct stat *buf);\n\nstruct path_entry {\n\tchar *name;\n\tregex_t *preg;\n\tstruct pathname *paths;\n};\n\nstruct pathname {\n\tint names;\n\tstruct path_entry *name;\n};\n\nstruct pathnames {\n\tint count;\n\tstruct pathname *path[0];\n};\n#define PATHS_ALLOC_SIZE 10\n\nstruct pathnames *paths = NULL;\nstruct pathname *path = NULL;\nstruct pathname *stickypath = NULL;\nint excluded(char *name, struct pathnames *paths, struct pathnames **new);\n\nint fragments = 0;\n\n#define FRAG_SIZE 32768\n\nstruct squashfs_fragment_entry *fragment_table = NULL;\nint fragments_outstanding = 0;\n\nint fragments_locked = FALSE;\n\n/* current inode number for directories and non directories */\nunsigned int inode_no = 1;\nunsigned int root_inode_number = 0;\n\n/* list of source dirs/files */\nint source = 0;\nchar **source_path;\n\n/* list of root directory entries read from original filesystem */\nint old_root_entries = 0;\nstruct old_root_entry_info {\n\tchar *name;\n\tstruct inode_info inode;\n};\nstruct old_root_entry_info *old_root_entry;\n\n/* restore orignal filesystem state if appending to existing filesystem is\n * cancelled */\nint appending = FALSE;\nchar *sdata_cache, *sdirectory_data_cache, *sdirectory_compressed;\n\nlong long sbytes, stotal_bytes;\n\nunsigned 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;\nint sfragments;\nint threads;\n\n/* flag whether destination file is a block device */\nint block_device = FALSE;\n\n/* flag indicating whether files are sorted using sort list(s) */\nint sorted = FALSE;\n\n/* save destination file name for deleting on error */\nchar *destination_file = NULL;\n\n/* recovery file for abnormal exit on appending */\nchar *recovery_file = NULL;\nint recover = TRUE;\n\nstruct id *id_hash_table[ID_ENTRIES];\nstruct id *id_table[SQUASHFS_IDS], *sid_table[SQUASHFS_IDS];\nunsigned int uid_count = 0, guid_count = 0;\nunsigned int sid_count = 0, suid_count = 0, sguid_count = 0;\n\nstruct cache *reader_buffer, *fragment_buffer, *reserve_cache;\nstruct cache *bwriter_buffer, *fwriter_buffer;\nstruct queue *to_reader, *to_deflate, *to_writer, *from_writer, *to_frag, *locked_fragment, *to_process_frag;\nstruct seq_queue *to_main;\npthread_t reader_thread, writer_thread, main_thread;\npthread_t *deflator_thread, *frag_deflator_thread, *frag_thread;\npthread_t *restore_thread = NULL;\npthread_mutex_t fragment_mutex = PTHREAD_MUTEX_INITIALIZER;\npthread_mutex_t pos_mutex = PTHREAD_MUTEX_INITIALIZER;\npthread_mutex_t dup_mutex = PTHREAD_MUTEX_INITIALIZER;\n\n/* user options that control parallelisation */\nint processors = -1;\nint bwriter_size;\n\n/* compression operations */\nstruct compressor *comp = NULL;\nint compressor_opt_parsed = FALSE;\nvoid *stream = NULL;\n\n/* xattr stats */\nunsigned int xattr_bytes = 0, total_xattr_bytes = 0;\n\n/* fragment to file mapping used when appending */\nint append_fragments = 0;\nstruct append_file **file_mapping;\n\nstatic char *read_from_disk(long long start, unsigned int avail_bytes);\nvoid add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type);\nstruct 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, int checksum_flag);\nstruct dir_info *dir_scan1(char *, char *, struct pathnames *, struct dir_ent *(_readdir) (struct dir_info *), int);\nvoid dir_scan2(struct dir_info *dir, struct pseudo *pseudo);\nvoid dir_scan3(struct dir_info *root, struct dir_info *dir);\nvoid dir_scan4(struct dir_info *dir);\nvoid dir_scan5(struct dir_info *dir);\nvoid dir_scan6(squashfs_inode * inode, struct dir_info *dir_info);\nstruct 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, int checksum_frag_flag);\nlong long generic_write_table(int, void *, int, void *, int);\nvoid restorefs();\nstruct dir_info *scan1_opendir(char *pathname, char *subpath, int depth);\nvoid write_filesystem_tables(struct squashfs_super_block *sBlk, int nopad);\nunsigned short get_checksum_mem(char *buff, int bytes);\nint get_physical_memory();\n\nvoid prep_exit() {\n\tif (restore_thread) {\n\t\tif (pthread_self() == *restore_thread) {\n\t\t\t/*\n\t\t\t * Recursive failure when trying to restore filesystem!\n\t\t\t * Nothing to do except to exit, otherwise we'll just\n\t\t\t * appear to hang.  The user should be able to restore\n\t\t\t * from the recovery file (which is why it was added, in\n\t\t\t * case of catastrophic failure in Mksquashfs)\n\t\t\t */\n\t\t\texit(1);\n\t\t} else {\n\t\t\t/* signal the restore thread to restore */\n\t\t\tpthread_kill(*restore_thread, SIGUSR1);\n\t\t\tpthread_exit(NULL);\n\t\t}\n\t} else if (delete) {\n\t\tif (destination_file && !block_device)\n\t\t\tunlink(destination_file);\n\t} else if (recovery_file)\n\t\tunlink(recovery_file);\n}\n\nint add_overflow(int a, int b) {\n\treturn (INT_MAX - a) < b;\n}\n\nint shift_overflow(int a, int shift) {\n\treturn (INT_MAX >> shift) < a;\n}\n\nint multiply_overflow(int a, int multiplier) {\n\treturn (INT_MAX / multiplier) < a;\n}\n\nint multiply_overflowll(long long a, int multiplier) {\n\treturn (LLONG_MAX / multiplier) < a;\n}\n\n#define MKINODE(A)\t((squashfs_inode)(((squashfs_inode) inode_bytes << 16) \\\n\t\t\t+ (((char *)A) - data_cache)))\n\nvoid restorefs() {\n\tERROR(\"Exiting - restoring original filesystem!\\n\\n\");\n\n\tbytes = sbytes;\n\tmemcpy(data_cache, sdata_cache, cache_bytes = scache_bytes);\n\tmemcpy(directory_data_cache, sdirectory_data_cache, sdirectory_cache_bytes);\n\tdirectory_cache_bytes = sdirectory_cache_bytes;\n\tinode_bytes = sinode_bytes;\n\tdirectory_bytes = sdirectory_bytes;\n\tmemcpy(directory_table + directory_bytes, sdirectory_compressed, sdirectory_compressed_bytes);\n\tdirectory_bytes += sdirectory_compressed_bytes;\n\ttotal_bytes = stotal_bytes;\n\ttotal_inode_bytes = stotal_inode_bytes;\n\ttotal_directory_bytes = stotal_directory_bytes;\n\tinode_count = sinode_count;\n\tfile_count = sfile_count;\n\tsym_count = ssym_count;\n\tdev_count = sdev_count;\n\tdir_count = sdir_count;\n\tfifo_count = sfifo_count;\n\tsock_count = ssock_count;\n\tdup_files = sdup_files;\n\tfragments = sfragments;\n\tid_count = sid_count;\n\trestore_xattrs();\n\twrite_filesystem_tables(&sBlk, nopad);\n\texit(1);\n}\n\nvoid sighandler() {\n\tEXIT_MKSQUASHFS();\n}\n\nint mangle2(void *strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) {\n\tint error, c_byte = 0;\n\n\tif (!uncompressed) {\n\t\tc_byte = compressor_compress(comp, strm, d, s, size, block_size, &error);\n\t\tif (c_byte == -1)\n\t\t\tBAD_ERROR(\"mangle2:: %s compress failed with error \" \"code %d\\n\", comp->name, error);\n\t}\n\n\tif (c_byte == 0 || c_byte >= size) {\n\t\tmemcpy(d, s, size);\n\t\treturn size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT);\n\t}\n\n\treturn c_byte;\n}\n\nint mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) {\n\treturn mangle2(stream, d, s, size, block_size, uncompressed, data_block);\n}\n\nvoid *get_inode(int req_size) {\n\tint data_space;\n\tunsigned short c_byte;\n\n\twhile (cache_bytes >= SQUASHFS_METADATA_SIZE) {\n\t\tif ((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) {\n\t\t\tvoid *it = realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2);\n\t\t\tif (it == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t\tinode_table = it;\n\t\t\tinode_size += (SQUASHFS_METADATA_SIZE << 1) + 2;\n\t\t}\n\n\t\tc_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0);\n\t\tTRACE(\"Inode block @ 0x%x, size %d\\n\", inode_bytes, c_byte);\n\t\tSQUASHFS_SWAP_SHORTS(&c_byte, inode_table + inode_bytes, 1);\n\t\tinode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET;\n\t\ttotal_inode_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET;\n\t\tmemmove(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE);\n\t\tcache_bytes -= SQUASHFS_METADATA_SIZE;\n\t}\n\n\tdata_space = (cache_size - cache_bytes);\n\tif (data_space < req_size) {\n\t\tint realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space;\n\n\t\tvoid *dc = realloc(data_cache, cache_size + realloc_size);\n\t\tif (dc == NULL)\n\t\t\tMEM_ERROR();\n\t\tcache_size += realloc_size;\n\t\tdata_cache = dc;\n\t}\n\n\tcache_bytes += req_size;\n\n\treturn data_cache + cache_bytes - req_size;\n}\n\nint read_bytes(int fd, void *buff, int bytes) {\n\tint res, count;\n\n\tfor (count = 0; count < bytes; count += res) {\n\t\tres = read(fd, buff + count, bytes - count);\n\t\tif (res < 1) {\n\t\t\tif (res == 0)\n\t\t\t\tgoto bytes_read;\n\t\t\telse if (errno != EINTR) {\n\t\t\t\tERROR(\"Read failed because %s\\n\", strerror(errno));\n\t\t\t\treturn -1;\n\t\t\t} else\n\t\t\t\tres = 0;\n\t\t}\n\t}\n\n bytes_read:\n\treturn count;\n}\n\nint read_fs_bytes(int fd, long long byte, int bytes, void *buff) {\n\toff_t off = byte;\n\tint res = 1;\n\n\tTRACE(\"read_fs_bytes: reading from position 0x%llx, bytes %d\\n\", byte, bytes);\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &pos_mutex);\n\tpthread_mutex_lock(&pos_mutex);\n\tif (lseek(fd, off, SEEK_SET) == -1) {\n\t\tERROR(\"read_fs_bytes: Lseek on destination failed because %s, \" \"offset=0x%llx\\n\", strerror(errno), off);\n\t\tres = 0;\n\t} else if (read_bytes(fd, buff, bytes) < bytes) {\n\t\tERROR(\"Read on destination failed\\n\");\n\t\tres = 0;\n\t}\n\n\tpthread_cleanup_pop(1);\n\treturn res;\n}\n\nint write_bytes(int fd, void *buff, int bytes) {\n\tint res, count;\n\n\tfor (count = 0; count < bytes; count += res) {\n\t\tres = write(fd, buff + count, bytes - count);\n\t\tif (res == -1) {\n\t\t\tif (errno != EINTR) {\n\t\t\t\tERROR(\"Write failed because %s\\n\", strerror(errno));\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tres = 0;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nvoid write_destination(int fd, long long byte, int bytes, void *buff) {\n\toff_t off = byte;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &pos_mutex);\n\tpthread_mutex_lock(&pos_mutex);\n\n\tif (lseek(fd, off, SEEK_SET) == -1) {\n\t\tERROR(\"write_destination: Lseek on destination \" \"failed because %s, offset=0x%llx\\n\", strerror(errno), off);\n\t\tBAD_ERROR(\"Probably out of space on output %s\\n\", block_device ? \"block device\" : \"filesystem\");\n\t}\n\n\tif (write_bytes(fd, buff, bytes) == -1)\n\t\tBAD_ERROR(\"Failed to write to output %s\\n\", block_device ? \"block device\" : \"filesystem\");\n\n\tpthread_cleanup_pop(1);\n}\n\nlong long write_inodes() {\n\tunsigned short c_byte;\n\tint avail_bytes;\n\tchar *datap = data_cache;\n\tlong long start_bytes = bytes;\n\n\twhile (cache_bytes) {\n\t\tif (inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) {\n\t\t\tvoid *it = realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2));\n\t\t\tif (it == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t\tinode_size += (SQUASHFS_METADATA_SIZE << 1) + 2;\n\t\t\tinode_table = it;\n\t\t}\n\t\tavail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes;\n\t\tc_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0);\n\t\tTRACE(\"Inode block @ 0x%x, size %d\\n\", inode_bytes, c_byte);\n\t\tSQUASHFS_SWAP_SHORTS(&c_byte, inode_table + inode_bytes, 1);\n\t\tinode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET;\n\t\ttotal_inode_bytes += avail_bytes + BLOCK_OFFSET;\n\t\tdatap += avail_bytes;\n\t\tcache_bytes -= avail_bytes;\n\t}\n\n\twrite_destination(fd, bytes, inode_bytes, inode_table);\n\tbytes += inode_bytes;\n\n\treturn start_bytes;\n}\n\nlong long write_directories() {\n\tunsigned short c_byte;\n\tint avail_bytes;\n\tchar *directoryp = directory_data_cache;\n\tlong long start_bytes = bytes;\n\n\twhile (directory_cache_bytes) {\n\t\tif (directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) {\n\t\t\tvoid *dt = realloc(directory_table,\n\t\t\t\t\t\t\t   directory_size + ((SQUASHFS_METADATA_SIZE << 1)\n\t\t\t\t\t\t\t\t\t\t\t\t + 2));\n\t\t\tif (dt == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t\tdirectory_size += (SQUASHFS_METADATA_SIZE << 1) + 2;\n\t\t\tdirectory_table = dt;\n\t\t}\n\t\tavail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes;\n\t\tc_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0);\n\t\tTRACE(\"Directory block @ 0x%x, size %d\\n\", directory_bytes, c_byte);\n\t\tSQUASHFS_SWAP_SHORTS(&c_byte, directory_table + directory_bytes, 1);\n\t\tdirectory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET;\n\t\ttotal_directory_bytes += avail_bytes + BLOCK_OFFSET;\n\t\tdirectoryp += avail_bytes;\n\t\tdirectory_cache_bytes -= avail_bytes;\n\t}\n\twrite_destination(fd, bytes, directory_bytes, directory_table);\n\tbytes += directory_bytes;\n\n\treturn start_bytes;\n}\n\nlong long write_id_table() {\n\tunsigned int id_bytes = SQUASHFS_ID_BYTES(id_count);\n\tunsigned int p[id_count];\n\tint i;\n\n\tTRACE(\"write_id_table: ids %d, id_bytes %d\\n\", id_count, id_bytes);\n\tfor (i = 0; i < id_count; i++) {\n\t\tTRACE(\"write_id_table: id index %d, id %d\", i, id_table[i]->id);\n\t\tSQUASHFS_SWAP_INTS(&id_table[i]->id, p + i, 1);\n\t}\n\n\treturn generic_write_table(id_bytes, p, 0, NULL, noI);\n}\n\nstruct id *get_id(unsigned int id) {\n\tint hash = ID_HASH(id);\n\tstruct id *entry = id_hash_table[hash];\n\n\tfor (; entry; entry = entry->next)\n\t\tif (entry->id == id)\n\t\t\tbreak;\n\n\treturn entry;\n}\n\nstruct id *create_id(unsigned int id) {\n\tint hash = ID_HASH(id);\n\tstruct id *entry = malloc(sizeof(struct id));\n\tif (entry == NULL)\n\t\tMEM_ERROR();\n\tentry->id = id;\n\tentry->index = id_count++;\n\tentry->flags = 0;\n\tentry->next = id_hash_table[hash];\n\tid_hash_table[hash] = entry;\n\tid_table[entry->index] = entry;\n\treturn entry;\n}\n\nunsigned int get_uid(unsigned int uid) {\n\tstruct id *entry = get_id(uid);\n\n\tif (entry == NULL) {\n\t\tif (id_count == SQUASHFS_IDS)\n\t\t\tBAD_ERROR(\"Out of uids!\\n\");\n\t\tentry = create_id(uid);\n\t}\n\n\tif ((entry->flags & ISA_UID) == 0) {\n\t\tentry->flags |= ISA_UID;\n\t\tuid_count++;\n\t}\n\n\treturn entry->index;\n}\n\nunsigned int get_guid(unsigned int guid) {\n\tstruct id *entry = get_id(guid);\n\n\tif (entry == NULL) {\n\t\tif (id_count == SQUASHFS_IDS)\n\t\t\tBAD_ERROR(\"Out of gids!\\n\");\n\t\tentry = create_id(guid);\n\t}\n\n\tif ((entry->flags & ISA_GID) == 0) {\n\t\tentry->flags |= ISA_GID;\n\t\tguid_count++;\n\t}\n\n\treturn entry->index;\n}\n\n#define ALLOC_SIZE 128\n\nchar *_pathname(struct dir_ent *dir_ent, char *pathname, int *size) {\n\tif (pathname == NULL) {\n\t\tpathname = malloc(ALLOC_SIZE);\n\t\tif (pathname == NULL)\n\t\t\tMEM_ERROR();\n\t}\n\n\tfor (;;) {\n\t\tint res = snprintf(pathname, *size, \"%s/%s\",\n\t\t\t\t\t\t   dir_ent->our_dir->pathname,\n\t\t\t\t\t\t   dir_ent->source_name ? : dir_ent->name);\n\n\t\tif (res < 0)\n\t\t\tBAD_ERROR(\"snprintf failed in pathname\\n\");\n\t\telse if (res >= *size) {\n\t\t\t/*\n\t\t\t * pathname is too small to contain the result, so\n\t\t\t * increase it and try again\n\t\t\t */\n\t\t\t*size = (res + ALLOC_SIZE) & ~(ALLOC_SIZE - 1);\n\t\t\tpathname = realloc(pathname, *size);\n\t\t\tif (pathname == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t} else\n\t\t\tbreak;\n\t}\n\n\treturn pathname;\n}\n\nchar *pathname(struct dir_ent *dir_ent) {\n\tstatic char *pathname = NULL;\n\tstatic int size = ALLOC_SIZE;\n\n\tif (dir_ent->nonstandard_pathname)\n\t\treturn dir_ent->nonstandard_pathname;\n\n\treturn pathname = _pathname(dir_ent, pathname, &size);\n}\n\nchar *pathname_reader(struct dir_ent *dir_ent) {\n\tstatic char *pathname = NULL;\n\tstatic int size = ALLOC_SIZE;\n\n\tif (dir_ent->nonstandard_pathname)\n\t\treturn dir_ent->nonstandard_pathname;\n\n\treturn pathname = _pathname(dir_ent, pathname, &size);\n}\n\nchar *subpathname(struct dir_ent *dir_ent) {\n\tstatic char *subpath = NULL;\n\tstatic int size = ALLOC_SIZE;\n\tint res;\n\n\tif (subpath == NULL) {\n\t\tsubpath = malloc(ALLOC_SIZE);\n\t\tif (subpath == NULL)\n\t\t\tMEM_ERROR();\n\t}\n\n\tfor (;;) {\n\t\tif (dir_ent->our_dir->subpath[0] != '\\0')\n\t\t\tres = snprintf(subpath, size, \"%s/%s\", dir_ent->our_dir->subpath, dir_ent->name);\n\t\telse\n\t\t\tres = snprintf(subpath, size, \"/%s\", dir_ent->name);\n\n\t\tif (res < 0)\n\t\t\tBAD_ERROR(\"snprintf failed in subpathname\\n\");\n\t\telse if (res >= size) {\n\t\t\t/*\n\t\t\t * subpath is too small to contain the result, so\n\t\t\t * increase it and try again\n\t\t\t */\n\t\t\tsize = (res + ALLOC_SIZE) & ~(ALLOC_SIZE - 1);\n\t\t\tsubpath = realloc(subpath, size);\n\t\t\tif (subpath == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t} else\n\t\t\tbreak;\n\t}\n\n\treturn subpath;\n}\n\ninline unsigned int get_inode_no(struct inode_info *inode) {\n\treturn inode->inode_number;\n}\n\ninline unsigned int get_parent_no(struct dir_info *dir) {\n\treturn dir->depth ? get_inode_no(dir->dir_ent->inode) : inode_no;\n}\n\nint 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) {\n\tstruct stat *buf = &dir_ent->inode->buf;\n\tunion squashfs_inode_header inode_header;\n\tstruct squashfs_base_inode_header *base = &inode_header.base;\n\tvoid *inode;\n\tchar *filename = pathname(dir_ent);\n\tint nlink = dir_ent->inode->nlink;\n\tint xattr = read_xattrs(dir_ent);\n\n\tswitch (type) {\n\tcase SQUASHFS_FILE_TYPE:\n\t\tif (dir_ent->inode->nlink > 1 || byte_size >= (1LL << 32) || start_block >= (1LL << 32) || sparse || IS_XATTR(xattr))\n\t\t\ttype = SQUASHFS_LREG_TYPE;\n\t\tbreak;\n\tcase SQUASHFS_DIR_TYPE:\n\t\tif (dir_info->dir_is_ldir || IS_XATTR(xattr))\n\t\t\ttype = SQUASHFS_LDIR_TYPE;\n\t\tbreak;\n\tcase SQUASHFS_SYMLINK_TYPE:\n\t\tif (IS_XATTR(xattr))\n\t\t\ttype = SQUASHFS_LSYMLINK_TYPE;\n\t\tbreak;\n\tcase SQUASHFS_BLKDEV_TYPE:\n\t\tif (IS_XATTR(xattr))\n\t\t\ttype = SQUASHFS_LBLKDEV_TYPE;\n\t\tbreak;\n\tcase SQUASHFS_CHRDEV_TYPE:\n\t\tif (IS_XATTR(xattr))\n\t\t\ttype = SQUASHFS_LCHRDEV_TYPE;\n\t\tbreak;\n\tcase SQUASHFS_FIFO_TYPE:\n\t\tif (IS_XATTR(xattr))\n\t\t\ttype = SQUASHFS_LFIFO_TYPE;\n\t\tbreak;\n\tcase SQUASHFS_SOCKET_TYPE:\n\t\tif (IS_XATTR(xattr))\n\t\t\ttype = SQUASHFS_LSOCKET_TYPE;\n\t\tbreak;\n\t}\n\n\tbase->mode = SQUASHFS_MODE(buf->st_mode);\n\tbase->uid = get_uid((unsigned int)global_uid == -1 ? buf->st_uid : global_uid);\n\tbase->inode_type = type;\n\tbase->guid = get_guid((unsigned int)global_gid == -1 ? buf->st_gid : global_gid);\n\tbase->mtime = buf->st_mtime;\n\tbase->inode_number = get_inode_no(dir_ent->inode);\n\n\tif (type == SQUASHFS_FILE_TYPE) {\n\t\tint i;\n\t\tstruct squashfs_reg_inode_header *reg = &inode_header.reg;\n\t\tsize_t off = offsetof(struct squashfs_reg_inode_header, block_list);\n\n\t\tinode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int));\n\t\treg->file_size = byte_size;\n\t\treg->start_block = start_block;\n\t\treg->fragment = fragment->index;\n\t\treg->offset = fragment->offset;\n\t\tSQUASHFS_SWAP_REG_INODE_HEADER(reg, inode);\n\t\tSQUASHFS_SWAP_INTS(block_list, inode + off, offset);\n\t\tTRACE(\"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);\n\t\tfor (i = 0; i < offset; i++)\n\t\t\tTRACE(\"Block %d, size %d\\n\", i, block_list[i]);\n\t} else if (type == SQUASHFS_LREG_TYPE) {\n\t\tint i;\n\t\tstruct squashfs_lreg_inode_header *reg = &inode_header.lreg;\n\t\tsize_t off = offsetof(struct squashfs_lreg_inode_header, block_list);\n\n\t\tinode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int));\n\t\treg->nlink = nlink;\n\t\treg->file_size = byte_size;\n\t\treg->start_block = start_block;\n\t\treg->fragment = fragment->index;\n\t\treg->offset = fragment->offset;\n\t\tif (sparse && sparse >= byte_size)\n\t\t\tsparse = byte_size - 1;\n\t\treg->sparse = sparse;\n\t\treg->xattr = xattr;\n\t\tSQUASHFS_SWAP_LREG_INODE_HEADER(reg, inode);\n\t\tSQUASHFS_SWAP_INTS(block_list, inode + off, offset);\n\t\tTRACE(\"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);\n\t\tfor (i = 0; i < offset; i++)\n\t\t\tTRACE(\"Block %d, size %d\\n\", i, block_list[i]);\n\t} else if (type == SQUASHFS_LDIR_TYPE) {\n\t\tint i;\n\t\tunsigned char *p;\n\t\tstruct squashfs_ldir_inode_header *dir = &inode_header.ldir;\n\t\tstruct cached_dir_index *index = dir_in->index;\n\t\tunsigned int i_count = dir_in->i_count;\n\t\tunsigned int i_size = dir_in->i_size;\n\n\t\tif (byte_size >= 1 << 27)\n\t\t\tBAD_ERROR(\"directory greater than 2^27-1 bytes!\\n\");\n\n\t\tinode = get_inode(sizeof(*dir) + i_size);\n\t\tdir->inode_type = SQUASHFS_LDIR_TYPE;\n\t\tdir->nlink = dir_ent->dir->directory_count + 2;\n\t\tdir->file_size = byte_size;\n\t\tdir->offset = offset;\n\t\tdir->start_block = start_block;\n\t\tdir->i_count = i_count;\n\t\tdir->parent_inode = get_parent_no(dir_ent->our_dir);\n\t\tdir->xattr = xattr;\n\n\t\tSQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode);\n\t\tp = inode + offsetof(struct squashfs_ldir_inode_header, index);\n\t\tfor (i = 0; i < i_count; i++) {\n\t\t\tSQUASHFS_SWAP_DIR_INDEX(&index[i].index, p);\n\t\t\tp += offsetof(struct squashfs_dir_index, name);\n\t\t\tmemcpy(p, index[i].name, index[i].index.size + 1);\n\t\t\tp += index[i].index.size + 1;\n\t\t}\n\t\tTRACE(\"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);\n\t} else if (type == SQUASHFS_DIR_TYPE) {\n\t\tstruct squashfs_dir_inode_header *dir = &inode_header.dir;\n\n\t\tinode = get_inode(sizeof(*dir));\n\t\tdir->nlink = dir_ent->dir->directory_count + 2;\n\t\tdir->file_size = byte_size;\n\t\tdir->offset = offset;\n\t\tdir->start_block = start_block;\n\t\tdir->parent_inode = get_parent_no(dir_ent->our_dir);\n\t\tSQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode);\n\t\tTRACE(\"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);\n\t} else if (type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) {\n\t\tstruct squashfs_dev_inode_header *dev = &inode_header.dev;\n\t\tunsigned int major = major(buf->st_rdev);\n\t\tunsigned int minor = minor(buf->st_rdev);\n\n\t\tif (major > 0xfff) {\n\t\t\tERROR(\"Major %d out of range in device node %s, \" \"truncating to %d\\n\", major, filename, major & 0xfff);\n\t\t\tmajor &= 0xfff;\n\t\t}\n\t\tif (minor > 0xfffff) {\n\t\t\tERROR(\"Minor %d out of range in device node %s, \" \"truncating to %d\\n\", minor, filename, minor & 0xfffff);\n\t\t\tminor &= 0xfffff;\n\t\t}\n\t\tinode = get_inode(sizeof(*dev));\n\t\tdev->nlink = nlink;\n\t\tdev->rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12);\n\t\tSQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode);\n\t\tTRACE(\"Device inode, rdev 0x%x, nlink %d\\n\", dev->rdev, nlink);\n\t} else if (type == SQUASHFS_LCHRDEV_TYPE || type == SQUASHFS_LBLKDEV_TYPE) {\n\t\tstruct squashfs_ldev_inode_header *dev = &inode_header.ldev;\n\t\tunsigned int major = major(buf->st_rdev);\n\t\tunsigned int minor = minor(buf->st_rdev);\n\n\t\tif (major > 0xfff) {\n\t\t\tERROR(\"Major %d out of range in device node %s, \" \"truncating to %d\\n\", major, filename, major & 0xfff);\n\t\t\tmajor &= 0xfff;\n\t\t}\n\t\tif (minor > 0xfffff) {\n\t\t\tERROR(\"Minor %d out of range in device node %s, \" \"truncating to %d\\n\", minor, filename, minor & 0xfffff);\n\t\t\tminor &= 0xfffff;\n\t\t}\n\t\tinode = get_inode(sizeof(*dev));\n\t\tdev->nlink = nlink;\n\t\tdev->rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12);\n\t\tdev->xattr = xattr;\n\t\tSQUASHFS_SWAP_LDEV_INODE_HEADER(dev, inode);\n\t\tTRACE(\"Device inode, rdev 0x%x, nlink %d\\n\", dev->rdev, nlink);\n\t} else if (type == SQUASHFS_SYMLINK_TYPE) {\n\t\tstruct squashfs_symlink_inode_header *symlink = &inode_header.symlink;\n\t\tint byte;\n\t\tchar buff[65536];\t\t/* overflow safe */\n\t\tsize_t off = offsetof(struct squashfs_symlink_inode_header, symlink);\n\n\t\tbyte = readlink(filename, buff, 65536);\n\t\tif (byte == -1) {\n\t\t\tERROR_START(\"Failed to read symlink %s\", filename);\n\t\t\tERROR_EXIT(\", creating empty symlink\\n\");\n\t\t\tbyte = 0;\n\t\t}\n\n\t\tif (byte == 65536) {\n\t\t\tERROR_START(\"Symlink %s is greater than 65536 bytes!\", filename);\n\t\t\tERROR_EXIT(\"  Creating empty symlink\\n\");\n\t\t\tbyte = 0;\n\t\t}\n\n\t\tinode = get_inode(sizeof(*symlink) + byte);\n\t\tsymlink->nlink = nlink;\n\t\tsymlink->symlink_size = byte;\n\t\tSQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode);\n\t\tstrncpy(inode + off, buff, byte);\n\t\tTRACE(\"Symbolic link inode, symlink_size %d, nlink %d\\n\", byte, nlink);\n\t} else if (type == SQUASHFS_LSYMLINK_TYPE) {\n\t\tstruct squashfs_symlink_inode_header *symlink = &inode_header.symlink;\n\t\tint byte;\n\t\tchar buff[65536];\t\t/* overflow safe */\n\t\tsize_t off = offsetof(struct squashfs_symlink_inode_header, symlink);\n\n\t\tbyte = readlink(filename, buff, 65536);\n\t\tif (byte == -1) {\n\t\t\tERROR_START(\"Failed to read symlink %s\", filename);\n\t\t\tERROR_EXIT(\", creating empty symlink\\n\");\n\t\t\tbyte = 0;\n\t\t}\n\n\t\tif (byte == 65536) {\n\t\t\tERROR_START(\"Symlink %s is greater than 65536 bytes!\", filename);\n\t\t\tERROR_EXIT(\"  Creating empty symlink\\n\");\n\t\t\tbyte = 0;\n\t\t}\n\n\t\tinode = get_inode(sizeof(*symlink) + byte + sizeof(unsigned int));\n\t\tsymlink->nlink = nlink;\n\t\tsymlink->symlink_size = byte;\n\t\tSQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode);\n\t\tstrncpy(inode + off, buff, byte);\n\t\tSQUASHFS_SWAP_INTS(&xattr, inode + off + byte, 1);\n\t\tTRACE(\"Symbolic link inode, symlink_size %d, nlink %d\\n\", byte, nlink);\n\t} else if (type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) {\n\t\tstruct squashfs_ipc_inode_header *ipc = &inode_header.ipc;\n\n\t\tinode = get_inode(sizeof(*ipc));\n\t\tipc->nlink = nlink;\n\t\tSQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode);\n\t\tTRACE(\"ipc inode, type %s, nlink %d\\n\", type == SQUASHFS_FIFO_TYPE ? \"fifo\" : \"socket\", nlink);\n\t} else if (type == SQUASHFS_LFIFO_TYPE || type == SQUASHFS_LSOCKET_TYPE) {\n\t\tstruct squashfs_lipc_inode_header *ipc = &inode_header.lipc;\n\n\t\tinode = get_inode(sizeof(*ipc));\n\t\tipc->nlink = nlink;\n\t\tipc->xattr = xattr;\n\t\tSQUASHFS_SWAP_LIPC_INODE_HEADER(ipc, inode);\n\t\tTRACE(\"ipc inode, type %s, nlink %d\\n\", type == SQUASHFS_FIFO_TYPE ? \"fifo\" : \"socket\", nlink);\n\t} else\n\t\tBAD_ERROR(\"Unrecognised inode %d in create_inode\\n\", type);\n\n\t*i_no = MKINODE(inode);\n\tinode_count++;\n\n\tTRACE(\"Created inode 0x%llx, type %d, uid %d, guid %d\\n\", *i_no, type, base->uid, base->guid);\n\n\treturn TRUE;\n}\n\nvoid add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) {\n\tunsigned char *buff;\n\tstruct squashfs_dir_entry idir;\n\tunsigned int start_block = inode >> 16;\n\tunsigned int offset = inode & 0xffff;\n\tunsigned int size = strlen(name);\n\tsize_t name_off = offsetof(struct squashfs_dir_entry, name);\n\n\tif (size > SQUASHFS_NAME_LEN) {\n\t\tsize = SQUASHFS_NAME_LEN;\n\t\tERROR(\"Filename is greater than %d characters, truncating! ...\" \"\\n\", SQUASHFS_NAME_LEN);\n\t}\n\n\tif (dir->p + sizeof(struct squashfs_dir_entry) + size + sizeof(struct squashfs_dir_header)\n\t\t>= dir->buff + dir->size) {\n\t\tbuff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE);\n\t\tif (buff == NULL)\n\t\t\tMEM_ERROR();\n\n\t\tdir->p = (dir->p - dir->buff) + buff;\n\t\tif (dir->entry_count_p)\n\t\t\tdir->entry_count_p = (dir->entry_count_p - dir->buff + buff);\n\t\tdir->index_count_p = dir->index_count_p - dir->buff + buff;\n\t\tdir->buff = buff;\n\t}\n\n\tif (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)\n\t\t< -32768) {\n\t\tif (dir->entry_count_p) {\n\t\t\tstruct squashfs_dir_header dir_header;\n\n\t\t\tif ((dir->p + sizeof(struct squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) {\n\t\t\t\tif (dir->i_count % I_COUNT_SIZE == 0) {\n\t\t\t\t\tdir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index));\n\t\t\t\t\tif (dir->index == NULL)\n\t\t\t\t\t\tMEM_ERROR();\n\t\t\t\t}\n\t\t\t\tdir->index[dir->i_count].index.index = dir->p - dir->buff;\n\t\t\t\tdir->index[dir->i_count].index.size = size - 1;\n\t\t\t\tdir->index[dir->i_count++].name = name;\n\t\t\t\tdir->i_size += sizeof(struct squashfs_dir_index)\n\t\t\t\t\t+ size;\n\t\t\t\tdir->index_count_p = dir->p;\n\t\t\t}\n\n\t\t\tdir_header.count = dir->entry_count - 1;\n\t\t\tdir_header.start_block = dir->start_block;\n\t\t\tdir_header.inode_number = dir->inode_number;\n\t\t\tSQUASHFS_SWAP_DIR_HEADER(&dir_header, dir->entry_count_p);\n\n\t\t}\n\n\t\tdir->entry_count_p = dir->p;\n\t\tdir->start_block = start_block;\n\t\tdir->entry_count = 0;\n\t\tdir->inode_number = inode_number;\n\t\tdir->p += sizeof(struct squashfs_dir_header);\n\t}\n\n\tidir.offset = offset;\n\tidir.type = type;\n\tidir.size = size - 1;\n\tidir.inode_number = ((long long)inode_number - dir->inode_number);\n\tSQUASHFS_SWAP_DIR_ENTRY(&idir, dir->p);\n\tstrncpy((char *)dir->p + name_off, name, size);\n\tdir->p += sizeof(struct squashfs_dir_entry) + size;\n\tdir->entry_count++;\n}\n\nvoid write_dir(squashfs_inode * inode, struct dir_info *dir_info, struct directory *dir) {\n\tunsigned int dir_size = dir->p - dir->buff;\n\tint data_space = directory_cache_size - directory_cache_bytes;\n\tunsigned int directory_block, directory_offset, i_count, index;\n\tunsigned short c_byte;\n\n\tif (data_space < dir_size) {\n\t\tint realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space;\n\n\t\tvoid *dc = realloc(directory_data_cache,\n\t\t\t\t\t\t   directory_cache_size + realloc_size);\n\t\tif (dc == NULL)\n\t\t\tMEM_ERROR();\n\t\tdirectory_cache_size += realloc_size;\n\t\tdirectory_data_cache = dc;\n\t}\n\n\tif (dir_size) {\n\t\tstruct squashfs_dir_header dir_header;\n\n\t\tdir_header.count = dir->entry_count - 1;\n\t\tdir_header.start_block = dir->start_block;\n\t\tdir_header.inode_number = dir->inode_number;\n\t\tSQUASHFS_SWAP_DIR_HEADER(&dir_header, dir->entry_count_p);\n\t\tmemcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size);\n\t}\n\tdirectory_offset = directory_cache_bytes;\n\tdirectory_block = directory_bytes;\n\tdirectory_cache_bytes += dir_size;\n\ti_count = 0;\n\tindex = SQUASHFS_METADATA_SIZE - directory_offset;\n\n\twhile (1) {\n\t\twhile (i_count < dir->i_count && dir->index[i_count].index.index < index)\n\t\t\tdir->index[i_count++].index.start_block = directory_bytes;\n\t\tindex += SQUASHFS_METADATA_SIZE;\n\n\t\tif (directory_cache_bytes < SQUASHFS_METADATA_SIZE)\n\t\t\tbreak;\n\n\t\tif ((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) {\n\t\t\tvoid *dt = realloc(directory_table,\n\t\t\t\t\t\t\t   directory_size + (SQUASHFS_METADATA_SIZE << 1)\n\t\t\t\t\t\t\t   + 2);\n\t\t\tif (dt == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t\tdirectory_size += SQUASHFS_METADATA_SIZE << 1;\n\t\t\tdirectory_table = dt;\n\t\t}\n\n\t\tc_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0);\n\t\tTRACE(\"Directory block @ 0x%x, size %d\\n\", directory_bytes, c_byte);\n\t\tSQUASHFS_SWAP_SHORTS(&c_byte, directory_table + directory_bytes, 1);\n\t\tdirectory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET;\n\t\ttotal_directory_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET;\n\t\tmemmove(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE);\n\t\tdirectory_cache_bytes -= SQUASHFS_METADATA_SIZE;\n\t}\n\n\tcreate_inode(inode, dir_info, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir, 0);\n\n#ifdef SQUASHFS_TRACE\n\t{\n\t\tunsigned char *dirp;\n\t\tint count;\n\n\t\tTRACE(\"Directory contents of inode 0x%llx\\n\", *inode);\n\t\tdirp = dir->buff;\n\t\twhile (dirp < dir->p) {\n\t\t\tchar buffer[SQUASHFS_NAME_LEN + 1];\n\t\t\tstruct squashfs_dir_entry idir, *idirp;\n\t\t\tstruct squashfs_dir_header dirh;\n\t\t\tSQUASHFS_SWAP_DIR_HEADER((struct squashfs_dir_header *)dirp, &dirh);\n\t\t\tcount = dirh.count + 1;\n\t\t\tdirp += sizeof(struct squashfs_dir_header);\n\n\t\t\tTRACE(\"\\tStart block 0x%x, count %d\\n\", dirh.start_block, count);\n\n\t\t\twhile (count--) {\n\t\t\t\tidirp = (struct squashfs_dir_entry *)dirp;\n\t\t\t\tSQUASHFS_SWAP_DIR_ENTRY(idirp, &idir);\n\t\t\t\tstrncpy(buffer, idirp->name, idir.size + 1);\n\t\t\t\tbuffer[idir.size + 1] = '\\0';\n\t\t\t\tTRACE(\"\\t\\tname %s, inode offset 0x%x, type \" \"%d\\n\", buffer, idir.offset, idir.type);\n\t\t\t\tdirp += sizeof(struct squashfs_dir_entry) + idir.size + 1;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\tdir_count++;\n}\n\nstatic struct file_buffer *get_fragment(struct fragment *fragment) {\n\tstruct squashfs_fragment_entry *disk_fragment;\n\tstruct file_buffer *buffer, *compressed_buffer;\n\tlong long start_block;\n\tint res, size, index = fragment->index;\n\tchar locked;\n\n\t/*\n\t * Lookup fragment block in cache.\n\t * If the fragment block doesn't exist, then get the compressed version\n\t * from the writer cache or off disk, and decompress it.\n\t *\n\t * This routine has two things which complicate the code:\n\t *\n\t *  1. Multiple threads can simultaneously lookup/create the\n\t *     same buffer.  This means a buffer needs to be \"locked\"\n\t *     when it is being filled in, to prevent other threads from\n\t *     using it when it is not ready.  This is because we now do\n\t *     fragment duplicate checking in parallel.\n\t *  2. We have two caches which need to be checked for the\n\t *     presence of fragment blocks: the normal fragment cache\n\t *     and a \"reserve\" cache.  The reserve cache is used to\n\t *     prevent an unnecessary pipeline stall when the fragment cache\n\t *     is full of fragments waiting to be compressed.\n\t */\n\n\tif (fragment->index == SQUASHFS_INVALID_FRAG)\n\t\treturn NULL;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &dup_mutex);\n\tpthread_mutex_lock(&dup_mutex);\n\n again:\n\tbuffer = cache_lookup_nowait(fragment_buffer, index, &locked);\n\tif (buffer) {\n\t\tpthread_mutex_unlock(&dup_mutex);\n\t\tif (locked)\n\t\t\t/* got a buffer being filled in.  Wait for it */\n\t\t\tcache_wait_unlock(buffer);\n\t\tgoto finished;\n\t}\n\n\t/* not in fragment cache, is it in the reserve cache? */\n\tbuffer = cache_lookup_nowait(reserve_cache, index, &locked);\n\tif (buffer) {\n\t\tpthread_mutex_unlock(&dup_mutex);\n\t\tif (locked)\n\t\t\t/* got a buffer being filled in.  Wait for it */\n\t\t\tcache_wait_unlock(buffer);\n\t\tgoto finished;\n\t}\n\n\t/* in neither cache, try to get it from the fragment cache */\n\tbuffer = cache_get_nowait(fragment_buffer, index);\n\tif (!buffer) {\n\t\t/*\n\t\t * no room, get it from the reserve cache, this is\n\t\t * dimensioned so it will always have space (no more than\n\t\t * processors + 1 can have an outstanding reserve buffer)\n\t\t */\n\t\tbuffer = cache_get_nowait(reserve_cache, index);\n\t\tif (!buffer) {\n\t\t\t/* failsafe */\n\t\t\tERROR(\"no space in reserve cache\\n\");\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\tpthread_mutex_unlock(&dup_mutex);\n\n\tcompressed_buffer = cache_lookup(fwriter_buffer, index);\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &fragment_mutex);\n\tpthread_mutex_lock(&fragment_mutex);\n\tdisk_fragment = &fragment_table[index];\n\tsize = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size);\n\tstart_block = disk_fragment->start_block;\n\tpthread_cleanup_pop(1);\n\n\tif (SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) {\n\t\tint error;\n\t\tchar *data;\n\n\t\tif (compressed_buffer)\n\t\t\tdata = compressed_buffer->data;\n\t\telse {\n\t\t\tdata = read_from_disk(start_block, size);\n\t\t\tif (data == NULL) {\n\t\t\t\tERROR(\"Failed to read fragment from output\" \" filesystem\\n\");\n\t\t\t\tBAD_ERROR(\"Output filesystem corrupted?\\n\");\n\t\t\t}\n\t\t}\n\n\t\tres = compressor_uncompress(comp, buffer->data, data, size, block_size, &error);\n\t\tif (res == -1)\n\t\t\tBAD_ERROR(\"%s uncompress failed with error code %d\\n\", comp->name, error);\n\t} else if (compressed_buffer)\n\t\tmemcpy(buffer->data, compressed_buffer->data, size);\n\telse {\n\t\tres = read_fs_bytes(fd, start_block, size, buffer->data);\n\t\tif (res == 0) {\n\t\t\tERROR(\"Failed to read fragment from output \" \"filesystem\\n\");\n\t\t\tBAD_ERROR(\"Output filesystem corrupted?\\n\");\n\t\t}\n\t}\n\n\tcache_unlock(buffer);\n\tcache_block_put(compressed_buffer);\n\n finished:\n\tpthread_cleanup_pop(0);\n\n\treturn buffer;\n}\n\nunsigned short get_fragment_checksum(struct file_info *file) {\n\tstruct file_buffer *frag_buffer;\n\tstruct append_file *append;\n\tint res, index = file->fragment->index;\n\tunsigned short checksum;\n\n\tif (index == SQUASHFS_INVALID_FRAG)\n\t\treturn 0;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &dup_mutex);\n\tpthread_mutex_lock(&dup_mutex);\n\tres = file->have_frag_checksum;\n\tchecksum = file->fragment_checksum;\n\tpthread_cleanup_pop(1);\n\n\tif (res)\n\t\treturn checksum;\n\n\tfrag_buffer = get_fragment(file->fragment);\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &dup_mutex);\n\n\tfor (append = file_mapping[index]; append; append = append->next) {\n\t\tint offset = append->file->fragment->offset;\n\t\tint size = append->file->fragment->size;\n\t\tunsigned short cksum = get_checksum_mem(frag_buffer->data + offset, size);\n\n\t\tif (file == append->file)\n\t\t\tchecksum = cksum;\n\n\t\tpthread_mutex_lock(&dup_mutex);\n\t\tappend->file->fragment_checksum = cksum;\n\t\tappend->file->have_frag_checksum = TRUE;\n\t\tpthread_mutex_unlock(&dup_mutex);\n\t}\n\n\tcache_block_put(frag_buffer);\n\tpthread_cleanup_pop(0);\n\n\treturn checksum;\n}\n\nvoid lock_fragments() {\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &fragment_mutex);\n\tpthread_mutex_lock(&fragment_mutex);\n\tfragments_locked = TRUE;\n\tpthread_cleanup_pop(1);\n}\n\nvoid unlock_fragments() {\n\tint frg, size;\n\tstruct file_buffer *write_buffer;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &fragment_mutex);\n\tpthread_mutex_lock(&fragment_mutex);\n\n\t/*\n\t * Note queue_empty() is inherently racy with respect to concurrent\n\t * queue get and pushes.  We avoid this because we're holding the\n\t * fragment_mutex which ensures no other threads can be using the\n\t * queue at this time.\n\t */\n\twhile (!queue_empty(locked_fragment)) {\n\t\twrite_buffer = queue_get(locked_fragment);\n\t\tfrg = write_buffer->block;\n\t\tsize = SQUASHFS_COMPRESSED_SIZE_BLOCK(fragment_table[frg].size);\n\t\tfragment_table[frg].start_block = bytes;\n\t\twrite_buffer->block = bytes;\n\t\tbytes += size;\n\t\tfragments_outstanding--;\n\t\tqueue_put(to_writer, write_buffer);\n\t\tTRACE(\"fragment_locked writing fragment %d, compressed size %d\" \"\\n\", frg, size);\n\t}\n\tfragments_locked = FALSE;\n\tpthread_cleanup_pop(1);\n}\n\n/* Called with the fragment_mutex locked */\nvoid add_pending_fragment(struct file_buffer *write_buffer, int c_byte, int fragment) {\n\tfragment_table[fragment].size = c_byte;\n\twrite_buffer->block = fragment;\n\n\tqueue_put(locked_fragment, write_buffer);\n}\n\nvoid write_fragment(struct file_buffer *fragment) {\n\tif (fragment == NULL)\n\t\treturn;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &fragment_mutex);\n\tpthread_mutex_lock(&fragment_mutex);\n\tfragment_table[fragment->block].unused = 0;\n\tfragments_outstanding++;\n\tqueue_put(to_frag, fragment);\n\tpthread_cleanup_pop(1);\n}\n\nstruct file_buffer *allocate_fragment() {\n\tstruct file_buffer *fragment = cache_get(fragment_buffer, fragments);\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &fragment_mutex);\n\tpthread_mutex_lock(&fragment_mutex);\n\n\tif (fragments % FRAG_SIZE == 0) {\n\t\tvoid *ft = realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(struct squashfs_fragment_entry));\n\t\tif (ft == NULL)\n\t\t\tMEM_ERROR();\n\t\tfragment_table = ft;\n\t}\n\n\tfragment->size = 0;\n\tfragment->block = fragments++;\n\n\tpthread_cleanup_pop(1);\n\n\treturn fragment;\n}\n\nstatic struct fragment empty_fragment = { SQUASHFS_INVALID_FRAG, 0, 0 };\n\nvoid free_fragment(struct fragment *fragment) {\n\tif (fragment != &empty_fragment)\n\t\tfree(fragment);\n}\n\nstruct fragment *get_and_fill_fragment(struct file_buffer *file_buffer, struct dir_ent *dir_ent) {\n\tstruct fragment *ffrg;\n\tstruct file_buffer **fragment;\n\n\tif (file_buffer == NULL || file_buffer->size == 0)\n\t\treturn &empty_fragment;\n\n\tfragment = eval_frag_actions(dir_ent);\n\n\tif ((*fragment) && (*fragment)->size + file_buffer->size > block_size) {\n\t\twrite_fragment(*fragment);\n\t\t*fragment = NULL;\n\t}\n\n\tffrg = malloc(sizeof(struct fragment));\n\tif (ffrg == NULL)\n\t\tMEM_ERROR();\n\n\tif (*fragment == NULL)\n\t\t*fragment = allocate_fragment();\n\n\tffrg->index = (*fragment)->block;\n\tffrg->offset = (*fragment)->size;\n\tffrg->size = file_buffer->size;\n\tmemcpy((*fragment)->data + (*fragment)->size, file_buffer->data, file_buffer->size);\n\t(*fragment)->size += file_buffer->size;\n\n\treturn ffrg;\n}\n\nlong long generic_write_table(int length, void *buffer, int length2, void *buffer2, int uncompressed) {\n\tint meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE;\n\tlong long *list, start_bytes;\n\tint compressed_size, i, list_size = meta_blocks * sizeof(long long);\n\tunsigned short c_byte;\n\tchar cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2];\n\n#ifdef SQUASHFS_TRACE\n\tlong long obytes = bytes;\n\tint olength = length;\n#endif\n\n\tlist = malloc(list_size);\n\tif (list == NULL)\n\t\tMEM_ERROR();\n\n\tfor (i = 0; i < meta_blocks; i++) {\n\t\tint avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length;\n\t\tc_byte = mangle(cbuffer + BLOCK_OFFSET, buffer + i * SQUASHFS_METADATA_SIZE, avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0);\n\t\tSQUASHFS_SWAP_SHORTS(&c_byte, cbuffer, 1);\n\t\tlist[i] = bytes;\n\t\tcompressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET;\n\t\tTRACE(\"block %d @ 0x%llx, compressed size %d\\n\", i, bytes, compressed_size);\n\t\twrite_destination(fd, bytes, compressed_size, cbuffer);\n\t\tbytes += compressed_size;\n\t\ttotal_bytes += avail_bytes;\n\t\tlength -= avail_bytes;\n\t}\n\n\tstart_bytes = bytes;\n\tif (length2) {\n\t\twrite_destination(fd, bytes, length2, buffer2);\n\t\tbytes += length2;\n\t\ttotal_bytes += length2;\n\t}\n\n\tSQUASHFS_INSWAP_LONG_LONGS(list, meta_blocks);\n\twrite_destination(fd, bytes, list_size, list);\n\tbytes += list_size;\n\ttotal_bytes += list_size;\n\n\tTRACE(\"generic_write_table: total uncompressed %d compressed %lld\\n\", olength, bytes - obytes);\n\n\tfree(list);\n\n\treturn start_bytes;\n}\n\nlong long write_fragment_table() {\n\tunsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments);\n\tint i;\n\n\tTRACE(\"write_fragment_table: fragments %d, frag_bytes %d\\n\", fragments, frag_bytes);\n\tfor (i = 0; i < fragments; i++) {\n\t\tTRACE(\"write_fragment_table: fragment %d, start_block 0x%llx, \" \"size %d\\n\", i, fragment_table[i].start_block, fragment_table[i].size);\n\t\tSQUASHFS_INSWAP_FRAGMENT_ENTRY(&fragment_table[i]);\n\t}\n\n\treturn generic_write_table(frag_bytes, fragment_table, 0, NULL, noF);\n}\n\nchar read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE];\nstatic char *read_from_disk(long long start, unsigned int avail_bytes) {\n\tint res;\n\n\tres = read_fs_bytes(fd, start, avail_bytes, read_from_file_buffer);\n\tif (res == 0)\n\t\treturn NULL;\n\n\treturn read_from_file_buffer;\n}\n\nchar read_from_file_buffer2[SQUASHFS_FILE_MAX_SIZE];\nchar *read_from_disk2(long long start, unsigned int avail_bytes) {\n\tint res;\n\n\tres = read_fs_bytes(fd, start, avail_bytes, read_from_file_buffer2);\n\tif (res == 0)\n\t\treturn NULL;\n\n\treturn read_from_file_buffer2;\n}\n\n/*\n * Compute 16 bit BSD checksum over the data\n */\nunsigned short get_checksum(char *buff, int bytes, unsigned short chksum) {\n\tunsigned char *b = (unsigned char *)buff;\n\n\twhile (bytes--) {\n\t\tchksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1;\n\t\tchksum += *b++;\n\t}\n\n\treturn chksum;\n}\n\nunsigned short get_checksum_disk(long long start, long long l, unsigned int *blocks) {\n\tunsigned short chksum = 0;\n\tunsigned int bytes;\n\tstruct file_buffer *write_buffer;\n\tint i;\n\n\tfor (i = 0; l; i++) {\n\t\tbytes = SQUASHFS_COMPRESSED_SIZE_BLOCK(blocks[i]);\n\t\tif (bytes == 0)\t\t\t/* sparse block */\n\t\t\tcontinue;\n\t\twrite_buffer = cache_lookup(bwriter_buffer, start);\n\t\tif (write_buffer) {\n\t\t\tchksum = get_checksum(write_buffer->data, bytes, chksum);\n\t\t\tcache_block_put(write_buffer);\n\t\t} else {\n\t\t\tvoid *data = read_from_disk(start, bytes);\n\t\t\tif (data == NULL) {\n\t\t\t\tERROR(\"Failed to checksum data from output\" \" filesystem\\n\");\n\t\t\t\tBAD_ERROR(\"Output filesystem corrupted?\\n\");\n\t\t\t}\n\n\t\t\tchksum = get_checksum(data, bytes, chksum);\n\t\t}\n\n\t\tl -= bytes;\n\t\tstart += bytes;\n\t}\n\n\treturn chksum;\n}\n\nunsigned short get_checksum_mem(char *buff, int bytes) {\n\treturn get_checksum(buff, bytes, 0);\n}\n\nunsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) {\n\tif (file_buffer == NULL)\n\t\treturn 0;\n\telse\n\t\treturn get_checksum(file_buffer->data, file_buffer->size, 0);\n}\n\n#define DUP_HASH(a) (a & 0xffff)\nvoid 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) {\n\tstruct fragment *frg;\n\tunsigned int *block_list = block_listp;\n\tstruct file_info *dupl_ptr = dupl[DUP_HASH(file_size)];\n\tstruct append_file *append_file;\n\tstruct file_info *file;\n\n\tif (!duplicate_checking || file_size == 0)\n\t\treturn;\n\n\tfor (; dupl_ptr; dupl_ptr = dupl_ptr->next) {\n\t\tif (file_size != dupl_ptr->file_size)\n\t\t\tcontinue;\n\t\tif (blocks != 0 && start != dupl_ptr->start)\n\t\t\tcontinue;\n\t\tif (fragment != dupl_ptr->fragment->index)\n\t\t\tcontinue;\n\t\tif (fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size))\n\t\t\tcontinue;\n\t\treturn;\n\t}\n\n\tfrg = malloc(sizeof(struct fragment));\n\tif (frg == NULL)\n\t\tMEM_ERROR();\n\n\tfrg->index = fragment;\n\tfrg->offset = offset;\n\tfrg->size = bytes;\n\n\tfile = add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE, FALSE);\n\n\tif (fragment == SQUASHFS_INVALID_FRAG)\n\t\treturn;\n\n\tappend_file = malloc(sizeof(struct append_file));\n\tif (append_file == NULL)\n\t\tMEM_ERROR();\n\n\tappend_file->file = file;\n\tappend_file->next = file_mapping[fragment];\n\tfile_mapping[fragment] = append_file;\n}\n\nint pre_duplicate(long long file_size) {\n\tstruct file_info *dupl_ptr = dupl[DUP_HASH(file_size)];\n\n\tfor (; dupl_ptr; dupl_ptr = dupl_ptr->next)\n\t\tif (dupl_ptr->file_size == file_size)\n\t\t\treturn TRUE;\n\n\treturn FALSE;\n}\n\nstruct 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, int checksum_frag_flag) {\n\tstruct file_info *dupl_ptr = malloc(sizeof(struct file_info));\n\n\tif (dupl_ptr == NULL)\n\t\tMEM_ERROR();\n\n\tdupl_ptr->file_size = file_size;\n\tdupl_ptr->bytes = bytes;\n\tdupl_ptr->block_list = block_list;\n\tdupl_ptr->start = start;\n\tdupl_ptr->fragment = fragment;\n\tdupl_ptr->checksum = checksum;\n\tdupl_ptr->fragment_checksum = fragment_checksum;\n\tdupl_ptr->have_frag_checksum = checksum_frag_flag;\n\tdupl_ptr->have_checksum = checksum_flag;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &dup_mutex);\n\tpthread_mutex_lock(&dup_mutex);\n\tdupl_ptr->next = dupl[DUP_HASH(file_size)];\n\tdupl[DUP_HASH(file_size)] = dupl_ptr;\n\tdup_files++;\n\tpthread_cleanup_pop(1);\n\n\treturn dupl_ptr;\n}\n\nstruct fragment *frag_duplicate(struct file_buffer *file_buffer, char *dont_put) {\n\tstruct file_info *dupl_ptr;\n\tstruct file_buffer *buffer;\n\tstruct file_info *dupl_start = file_buffer->dupl_start;\n\tlong long file_size = file_buffer->file_size;\n\tunsigned short checksum = file_buffer->checksum;\n\tint res;\n\n\tif (file_buffer->duplicate) {\n\t\tTRACE(\"Found duplicate file, fragment %d, size %d, offset %d, \" \"checksum 0x%x\\n\", dupl_start->fragment->index, file_size, dupl_start->fragment->offset, checksum);\n\t\t*dont_put = TRUE;\n\t\treturn dupl_start->fragment;\n\t} else {\n\t\t*dont_put = FALSE;\n\t\tdupl_ptr = dupl[DUP_HASH(file_size)];\n\t}\n\n\tfor (; dupl_ptr && dupl_ptr != dupl_start; dupl_ptr = dupl_ptr->next) {\n\t\tif (file_size == dupl_ptr->file_size && file_size == dupl_ptr->fragment->size) {\n\t\t\tif (get_fragment_checksum(dupl_ptr) == checksum) {\n\t\t\t\tbuffer = get_fragment(dupl_ptr->fragment);\n\t\t\t\tres = memcmp(file_buffer->data, buffer->data + dupl_ptr->fragment->offset, file_size);\n\t\t\t\tcache_block_put(buffer);\n\t\t\t\tif (res == 0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!dupl_ptr || dupl_ptr == dupl_start)\n\t\treturn NULL;\n\n\tTRACE(\"Found duplicate file, fragment %d, size %d, offset %d, \" \"checksum 0x%x\\n\", dupl_ptr->fragment->index, file_size, dupl_ptr->fragment->offset, checksum);\n\n\treturn dupl_ptr->fragment;\n}\n\nstruct 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, int checksum_flag) {\n\tstruct file_info *dupl_ptr = dupl[DUP_HASH(file_size)];\n\tint frag_bytes = file_buffer ? file_buffer->size : 0;\n\tunsigned short fragment_checksum = file_buffer ? file_buffer->checksum : 0;\n\n\tfor (; dupl_ptr; dupl_ptr = dupl_ptr->next)\n\t\tif (file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) {\n\t\t\tlong long target_start, dup_start = dupl_ptr->start;\n\t\t\tint block;\n\n\t\t\tif (memcmp(*block_list, dupl_ptr->block_list, blocks * sizeof(unsigned int)) != 0)\n\t\t\t\tcontinue;\n\n\t\t\tif (checksum_flag == FALSE) {\n\t\t\t\tchecksum = get_checksum_disk(*start, bytes, *block_list);\n\t\t\t\tchecksum_flag = TRUE;\n\t\t\t}\n\n\t\t\tif (!dupl_ptr->have_checksum) {\n\t\t\t\tdupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list);\n\t\t\t\tdupl_ptr->have_checksum = TRUE;\n\t\t\t}\n\n\t\t\tif (checksum != dupl_ptr->checksum || fragment_checksum != get_fragment_checksum(dupl_ptr))\n\t\t\t\tcontinue;\n\n\t\t\ttarget_start = *start;\n\t\t\tfor (block = 0; block < blocks; block++) {\n\t\t\t\tint size = SQUASHFS_COMPRESSED_SIZE_BLOCK((*block_list)[block]);\n\t\t\t\tstruct file_buffer *target_buffer = NULL;\n\t\t\t\tstruct file_buffer *dup_buffer = NULL;\n\t\t\t\tchar *target_data, *dup_data;\n\t\t\t\tint res;\n\n\t\t\t\tif (size == 0)\n\t\t\t\t\tcontinue;\n\t\t\t\ttarget_buffer = cache_lookup(bwriter_buffer, target_start);\n\t\t\t\tif (target_buffer)\n\t\t\t\t\ttarget_data = target_buffer->data;\n\t\t\t\telse {\n\t\t\t\t\ttarget_data = read_from_disk(target_start, size);\n\t\t\t\t\tif (target_data == NULL) {\n\t\t\t\t\t\tERROR(\"Failed to read data from\" \" output filesystem\\n\");\n\t\t\t\t\t\tBAD_ERROR(\"Output filesystem\" \" corrupted?\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tdup_buffer = cache_lookup(bwriter_buffer, dup_start);\n\t\t\t\tif (dup_buffer)\n\t\t\t\t\tdup_data = dup_buffer->data;\n\t\t\t\telse {\n\t\t\t\t\tdup_data = read_from_disk2(dup_start, size);\n\t\t\t\t\tif (dup_data == NULL) {\n\t\t\t\t\t\tERROR(\"Failed to read data from\" \" output filesystem\\n\");\n\t\t\t\t\t\tBAD_ERROR(\"Output filesystem\" \" corrupted?\\n\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tres = memcmp(target_data, dup_data, size);\n\t\t\t\tcache_block_put(target_buffer);\n\t\t\t\tcache_block_put(dup_buffer);\n\t\t\t\tif (res != 0)\n\t\t\t\t\tbreak;\n\t\t\t\ttarget_start += size;\n\t\t\t\tdup_start += size;\n\t\t\t}\n\t\t\tif (block == blocks) {\n\t\t\t\tstruct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment);\n\n\t\t\t\tif (frag_bytes == 0 || memcmp(file_buffer->data, frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes) == 0) {\n\t\t\t\t\tTRACE(\"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);\n\t\t\t\t\t*block_list = dupl_ptr->block_list;\n\t\t\t\t\t*start = dupl_ptr->start;\n\t\t\t\t\t*fragment = dupl_ptr->fragment;\n\t\t\t\t\tcache_block_put(frag_buffer);\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\tcache_block_put(frag_buffer);\n\t\t\t}\n\t\t}\n\n\treturn add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag, TRUE);\n}\n\ninline int is_fragment(struct inode_info *inode) {\n\tint file_size = inode->buf.st_size;\n\n\t/*\n\t * If this block is to be compressed differently to the\n\t * fragment compression then it cannot be a fragment\n\t */\n\tif (inode->noF != noF)\n\t\treturn FALSE;\n\n\treturn !inode->no_fragments && file_size && (file_size < block_size || (inode->always_use_fragments && file_size & (block_size - 1)));\n}\n\nvoid put_file_buffer(struct file_buffer *file_buffer) {\n\t/*\n\t * Decide where to send the file buffer:\n\t * - compressible non-fragment blocks go to the deflate threads,\n\t * - fragments go to the process fragment threads,\n\t * - all others go directly to the main thread\n\t */\n\tif (file_buffer->error) {\n\t\tfile_buffer->fragment = 0;\n\t\tseq_queue_put(to_main, file_buffer);\n\t} else if (file_buffer->file_size == 0)\n\t\tseq_queue_put(to_main, file_buffer);\n\telse if (file_buffer->fragment)\n\t\tqueue_put(to_process_frag, file_buffer);\n\telse\n\t\tqueue_put(to_deflate, file_buffer);\n}\n\nstatic int seq = 0;\nvoid reader_read_process(struct dir_ent *dir_ent) {\n\tlong long bytes = 0;\n\tstruct inode_info *inode = dir_ent->inode;\n\tstruct file_buffer *prev_buffer = NULL, *file_buffer;\n\tint status, byte, res, child;\n\tint file = pseudo_exec_file(get_pseudo_file(inode->pseudo_id), &child);\n\n\tif (!file) {\n\t\tfile_buffer = cache_get_nohash(reader_buffer);\n\t\tfile_buffer->sequence = seq++;\n\t\tgoto read_err;\n\t}\n\n\twhile (1) {\n\t\tfile_buffer = cache_get_nohash(reader_buffer);\n\t\tfile_buffer->sequence = seq++;\n\t\tfile_buffer->noD = inode->noD;\n\n\t\tbyte = read_bytes(file, file_buffer->data, block_size);\n\t\tif (byte == -1)\n\t\t\tgoto read_err2;\n\n\t\tfile_buffer->size = byte;\n\t\tfile_buffer->file_size = -1;\n\t\tfile_buffer->error = FALSE;\n\t\tfile_buffer->fragment = FALSE;\n\t\tbytes += byte;\n\n\t\tif (byte == 0)\n\t\t\tbreak;\n\n\t\t/*\n\t\t * Update progress bar size.  This is done\n\t\t * on every block rather than waiting for all blocks to be\n\t\t * read incase write_file_process() is running in parallel\n\t\t * with this.  Otherwise the current progress bar position\n\t\t * may get ahead of the progress bar size.\n\t\t */\n\t\tprogress_bar_size(1);\n\n\t\tif (prev_buffer)\n\t\t\tput_file_buffer(prev_buffer);\n\t\tprev_buffer = file_buffer;\n\t}\n\n\t/*\n\t * Update inode file size now that the size of the dynamic pseudo file\n\t * is known.  This is needed for the -info option.\n\t */\n\tinode->buf.st_size = bytes;\n\n\tres = waitpid(child, &status, 0);\n\tclose(file);\n\n\tif (res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)\n\t\tgoto read_err;\n\n\tif (prev_buffer == NULL)\n\t\tprev_buffer = file_buffer;\n\telse {\n\t\tcache_block_put(file_buffer);\n\t\tseq--;\n\t}\n\tprev_buffer->file_size = bytes;\n\tprev_buffer->fragment = is_fragment(inode);\n\tput_file_buffer(prev_buffer);\n\n\treturn;\n\n read_err2:\n\tclose(file);\n read_err:\n\tif (prev_buffer) {\n\t\tcache_block_put(file_buffer);\n\t\tseq--;\n\t\tfile_buffer = prev_buffer;\n\t}\n\tfile_buffer->error = TRUE;\n\tput_file_buffer(file_buffer);\n}\n\nvoid reader_read_file(struct dir_ent *dir_ent) {\n\tstruct stat *buf = &dir_ent->inode->buf, buf2;\n\tstruct file_buffer *file_buffer;\n\tint blocks, file, res;\n\tlong long bytes, read_size;\n\tstruct inode_info *inode = dir_ent->inode;\n\n\tif (inode->read)\n\t\treturn;\n\n\tinode->read = TRUE;\n again:\n\tbytes = 0;\n\tread_size = buf->st_size;\n\tblocks = (read_size + block_size - 1) >> block_log;\n\n\tfile = open(pathname_reader(dir_ent), O_RDONLY);\n\tif (file == -1) {\n\t\tfile_buffer = cache_get_nohash(reader_buffer);\n\t\tfile_buffer->sequence = seq++;\n\t\tgoto read_err2;\n\t}\n\n\tdo {\n\t\tfile_buffer = cache_get_nohash(reader_buffer);\n\t\tfile_buffer->file_size = read_size;\n\t\tfile_buffer->sequence = seq++;\n\t\tfile_buffer->noD = inode->noD;\n\t\tfile_buffer->error = FALSE;\n\n\t\t/*\n\t\t * Always try to read block_size bytes from the file rather\n\t\t * than expected bytes (which will be less than the block_size\n\t\t * at the file tail) to check that the file hasn't grown\n\t\t * since being stated.  If it is longer (or shorter) than\n\t\t * expected, then restat, and try again.  Note the special\n\t\t * case where the file is an exact multiple of the block_size\n\t\t * is dealt with later.\n\t\t */\n\t\tfile_buffer->size = read_bytes(file, file_buffer->data, block_size);\n\t\tif (file_buffer->size == -1)\n\t\t\tgoto read_err;\n\n\t\tbytes += file_buffer->size;\n\n\t\tif (blocks > 1) {\n\t\t\t/* non-tail block should be exactly block_size */\n\t\t\tif (file_buffer->size < block_size)\n\t\t\t\tgoto restat;\n\n\t\t\tfile_buffer->fragment = FALSE;\n\t\t\tput_file_buffer(file_buffer);\n\t\t}\n\t} while (--blocks > 0);\n\n\t/* Overall size including tail should match */\n\tif (read_size != bytes)\n\t\tgoto restat;\n\n\tif (read_size && read_size % block_size == 0) {\n\t\t/*\n\t\t * Special case where we've not tried to read past the end of\n\t\t * the file.  We expect to get EOF, i.e. the file isn't larger\n\t\t * than we expect.\n\t\t */\n\t\tchar buffer;\n\t\tint res;\n\n\t\tres = read_bytes(file, &buffer, 1);\n\t\tif (res == -1)\n\t\t\tgoto read_err;\n\n\t\tif (res != 0)\n\t\t\tgoto restat;\n\t}\n\n\tfile_buffer->fragment = is_fragment(inode);\n\tput_file_buffer(file_buffer);\n\n\tclose(file);\n\n\treturn;\n\n restat:\n\tres = fstat(file, &buf2);\n\tif (res == -1) {\n\t\tERROR(\"Cannot stat dir/file %s because %s\\n\", pathname_reader(dir_ent), strerror(errno));\n\t\tgoto read_err;\n\t}\n\n\tif (read_size != buf2.st_size) {\n\t\tclose(file);\n\t\tmemcpy(buf, &buf2, sizeof(struct stat));\n\t\tfile_buffer->error = 2;\n\t\tput_file_buffer(file_buffer);\n\t\tgoto again;\n\t}\n read_err:\n\tclose(file);\n read_err2:\n\tfile_buffer->error = TRUE;\n\tput_file_buffer(file_buffer);\n}\n\nvoid reader_scan(struct dir_info *dir) {\n\tstruct dir_ent *dir_ent = dir->list;\n\n\tfor (; dir_ent; dir_ent = dir_ent->next) {\n\t\tstruct stat *buf = &dir_ent->inode->buf;\n\t\tif (dir_ent->inode->root_entry)\n\t\t\tcontinue;\n\n\t\tif (IS_PSEUDO_PROCESS(dir_ent->inode)) {\n\t\t\treader_read_process(dir_ent);\n\t\t\tcontinue;\n\t\t}\n\n\t\tswitch (buf->st_mode & S_IFMT) {\n\t\tcase S_IFREG:\n\t\t\treader_read_file(dir_ent);\n\t\t\tbreak;\n\t\tcase S_IFDIR:\n\t\t\treader_scan(dir_ent->dir);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid *reader(void *arg) {\n\tif (!sorted)\n\t\treader_scan(queue_get(to_reader));\n\telse {\n\t\tint i;\n\t\tstruct priority_entry *entry;\n\n\t\tqueue_get(to_reader);\n\t\tfor (i = 65535; i >= 0; i--)\n\t\t\tfor (entry = priority_list[i]; entry; entry = entry->next)\n\t\t\t\treader_read_file(entry->dir);\n\t}\n\n\tpthread_exit(NULL);\n}\n\nvoid *writer(void *arg) {\n\twhile (1) {\n\t\tstruct file_buffer *file_buffer = queue_get(to_writer);\n\t\toff_t off;\n\n\t\tif (file_buffer == NULL) {\n\t\t\tqueue_put(from_writer, NULL);\n\t\t\tcontinue;\n\t\t}\n\n\t\toff = file_buffer->block;\n\n\t\tpthread_cleanup_push((void *)pthread_mutex_unlock, &pos_mutex);\n\t\tpthread_mutex_lock(&pos_mutex);\n\n\t\tif (lseek(fd, off, SEEK_SET) == -1) {\n\t\t\tERROR(\"writer: Lseek on destination failed because \" \"%s, offset=0x%llx\\n\", strerror(errno), off);\n\t\t\tBAD_ERROR(\"Probably out of space on output \" \"%s\\n\", block_device ? \"block device\" : \"filesystem\");\n\t\t}\n\n\t\tif (write_bytes(fd, file_buffer->data, file_buffer->size) == -1)\n\t\t\tBAD_ERROR(\"Failed to write to output %s\\n\", block_device ? \"block device\" : \"filesystem\");\n\n\t\tpthread_cleanup_pop(1);\n\n\t\tcache_block_put(file_buffer);\n\t}\n}\n\nint all_zero(struct file_buffer *file_buffer) {\n\tint i;\n\tlong entries = file_buffer->size / sizeof(long);\n\tlong *p = (long *)file_buffer->data;\n\n\tfor (i = 0; i < entries && p[i] == 0; i++) ;\n\n\tif (i == entries) {\n\t\tfor (i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++) ;\n\n\t\treturn i == file_buffer->size;\n\t}\n\n\treturn 0;\n}\n\nvoid *deflator(void *arg) {\n\tstruct file_buffer *write_buffer = cache_get_nohash(bwriter_buffer);\n\tvoid *stream = NULL;\n\tint res;\n\n\tres = compressor_init(comp, &stream, block_size, 1);\n\tif (res)\n\t\tBAD_ERROR(\"deflator:: compressor_init failed\\n\");\n\n\twhile (1) {\n\t\tstruct file_buffer *file_buffer = queue_get(to_deflate);\n\n\t\tif (sparse_files && all_zero(file_buffer)) {\n\t\t\tfile_buffer->c_byte = 0;\n\t\t\tseq_queue_put(to_main, file_buffer);\n\t\t} else {\n\t\t\twrite_buffer->c_byte = mangle2(stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, file_buffer->noD, 1);\n\t\t\twrite_buffer->sequence = file_buffer->sequence;\n\t\t\twrite_buffer->file_size = file_buffer->file_size;\n\t\t\twrite_buffer->block = file_buffer->block;\n\t\t\twrite_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte);\n\t\t\twrite_buffer->fragment = FALSE;\n\t\t\twrite_buffer->error = FALSE;\n\t\t\tcache_block_put(file_buffer);\n\t\t\tseq_queue_put(to_main, write_buffer);\n\t\t\twrite_buffer = cache_get_nohash(bwriter_buffer);\n\t\t}\n\t}\n}\n\nvoid *frag_deflator(void *arg) {\n\tvoid *stream = NULL;\n\tint res;\n\n\tres = compressor_init(comp, &stream, block_size, 1);\n\tif (res)\n\t\tBAD_ERROR(\"frag_deflator:: compressor_init failed\\n\");\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &fragment_mutex);\n\n\twhile (1) {\n\t\tint c_byte, compressed_size;\n\t\tstruct file_buffer *file_buffer = queue_get(to_frag);\n\t\tstruct file_buffer *write_buffer = cache_get(fwriter_buffer, file_buffer->block);\n\n\t\tc_byte = mangle2(stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1);\n\t\tcompressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);\n\t\twrite_buffer->size = compressed_size;\n\t\tpthread_mutex_lock(&fragment_mutex);\n\t\tif (fragments_locked == FALSE) {\n\t\t\tfragment_table[file_buffer->block].size = c_byte;\n\t\t\tfragment_table[file_buffer->block].start_block = bytes;\n\t\t\twrite_buffer->block = bytes;\n\t\t\tbytes += compressed_size;\n\t\t\tfragments_outstanding--;\n\t\t\tpthread_mutex_unlock(&fragment_mutex);\n\t\t\tqueue_put(to_writer, write_buffer);\n\t\t\tTRACE(\"Writing fragment %lld, uncompressed size %d, \" \"compressed size %d\\n\", file_buffer->block, file_buffer->size, compressed_size);\n\t\t} else {\n\t\t\tadd_pending_fragment(write_buffer, c_byte, file_buffer->block);\n\t\t\tpthread_mutex_unlock(&fragment_mutex);\n\t\t}\n\t\tcache_block_put(file_buffer);\n\t}\n\n\tpthread_cleanup_pop(0);\n}\n\nstruct file_buffer *get_file_buffer() {\n\tstruct file_buffer *file_buffer = seq_queue_get(to_main);\n\n\treturn file_buffer;\n}\n\nvoid write_file_empty(squashfs_inode * inode, struct dir_ent *dir_ent, struct file_buffer *file_buffer, int *duplicate_file) {\n\tfile_count++;\n\t*duplicate_file = FALSE;\n\tcache_block_put(file_buffer);\n\tcreate_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL, 0);\n}\n\nvoid write_file_frag(squashfs_inode * inode, struct dir_ent *dir_ent, struct file_buffer *file_buffer, int *duplicate_file) {\n\tint size = file_buffer->file_size;\n\tstruct fragment *fragment;\n\tunsigned short checksum = file_buffer->checksum;\n\tchar dont_put;\n\n\tfragment = frag_duplicate(file_buffer, &dont_put);\n\t*duplicate_file = !fragment;\n\tif (!fragment) {\n\t\tfragment = get_and_fill_fragment(file_buffer, dir_ent);\n\t\tif (duplicate_checking)\n\t\t\tadd_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE, TRUE);\n\t}\n\n\tif (dont_put)\n\t\tfree(file_buffer);\n\telse\n\t\tcache_block_put(file_buffer);\n\n\ttotal_bytes += size;\n\tfile_count++;\n\n\tinc_progress_bar();\n\n\tcreate_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0);\n\n\tif (!duplicate_checking)\n\t\tfree_fragment(fragment);\n}\n\nint write_file_process(squashfs_inode * inode, struct dir_ent *dir_ent, struct file_buffer *read_buffer, int *duplicate_file) {\n\tlong long read_size, file_bytes, start;\n\tstruct fragment *fragment;\n\tunsigned int *block_list = NULL;\n\tint block = 0, status;\n\tlong long sparse = 0;\n\tstruct file_buffer *fragment_buffer = NULL;\n\n\t*duplicate_file = FALSE;\n\n\tlock_fragments();\n\n\tfile_bytes = 0;\n\tstart = bytes;\n\twhile (1) {\n\t\tread_size = read_buffer->file_size;\n\t\tif (read_buffer->fragment)\n\t\t\tfragment_buffer = read_buffer;\n\t\telse {\n\t\t\tblock_list = realloc(block_list, (block + 1) * sizeof(unsigned int));\n\t\t\tif (block_list == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t\tblock_list[block++] = read_buffer->c_byte;\n\t\t\tif (read_buffer->c_byte) {\n\t\t\t\tread_buffer->block = bytes;\n\t\t\t\tbytes += read_buffer->size;\n\t\t\t\tcache_hash(read_buffer, read_buffer->block);\n\t\t\t\tfile_bytes += read_buffer->size;\n\t\t\t\tqueue_put(to_writer, read_buffer);\n\t\t\t} else {\n\t\t\t\tsparse += read_buffer->size;\n\t\t\t\tcache_block_put(read_buffer);\n\t\t\t}\n\t\t}\n\t\tinc_progress_bar();\n\n\t\tif (read_size != -1)\n\t\t\tbreak;\n\n\t\tread_buffer = get_file_buffer();\n\t\tif (read_buffer->error)\n\t\t\tgoto read_err;\n\t}\n\n\tunlock_fragments();\n\tfragment = get_and_fill_fragment(fragment_buffer, dir_ent);\n\n\tif (duplicate_checking)\n\t\tadd_non_dup(read_size, file_bytes, block_list, start, fragment, 0, fragment_buffer ? fragment_buffer->checksum : 0, FALSE, TRUE);\n\tcache_block_put(fragment_buffer);\n\tfile_count++;\n\ttotal_bytes += read_size;\n\n\tcreate_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, block, block_list, fragment, NULL, sparse);\n\n\tif (duplicate_checking == FALSE) {\n\t\tfree(block_list);\n\t\tfree_fragment(fragment);\n\t}\n\n\treturn 0;\n\n read_err:\n\tdec_progress_bar(block);\n\tstatus = read_buffer->error;\n\tbytes = start;\n\tif (!block_device) {\n\t\tint res;\n\n\t\tqueue_put(to_writer, NULL);\n\t\tif (queue_get(from_writer) != 0)\n\t\t\tEXIT_MKSQUASHFS();\n\t\tres = ftruncate(fd, bytes);\n\t\tif (res != 0)\n\t\t\tBAD_ERROR(\"Failed to truncate dest file because %s\\n\", strerror(errno));\n\t}\n\tunlock_fragments();\n\tfree(block_list);\n\tcache_block_put(read_buffer);\n\treturn status;\n}\n\nint write_file_blocks_dup(squashfs_inode * inode, struct dir_ent *dir_ent, struct file_buffer *read_buffer, int *duplicate_file) {\n\tint block, thresh;\n\tlong long read_size = read_buffer->file_size;\n\tlong long file_bytes, dup_start, start;\n\tstruct fragment *fragment;\n\tstruct file_info *dupl_ptr;\n\tint blocks = (read_size + block_size - 1) >> block_log;\n\tunsigned int *block_list, *block_listp;\n\tstruct file_buffer **buffer_list;\n\tint status;\n\tlong long sparse = 0;\n\tstruct file_buffer *fragment_buffer = NULL;\n\n\tblock_list = malloc(blocks * sizeof(unsigned int));\n\tif (block_list == NULL)\n\t\tMEM_ERROR();\n\tblock_listp = block_list;\n\n\tbuffer_list = malloc(blocks * sizeof(struct file_buffer *));\n\tif (buffer_list == NULL)\n\t\tMEM_ERROR();\n\n\tlock_fragments();\n\n\tfile_bytes = 0;\n\tstart = dup_start = bytes;\n\tthresh = blocks > bwriter_size ? blocks - bwriter_size : 0;\n\n\tfor (block = 0; block < blocks;) {\n\t\tif (read_buffer->fragment) {\n\t\t\tblock_list[block] = 0;\n\t\t\tbuffer_list[block] = NULL;\n\t\t\tfragment_buffer = read_buffer;\n\t\t\tblocks = read_size >> block_log;\n\t\t} else {\n\t\t\tblock_list[block] = read_buffer->c_byte;\n\n\t\t\tif (read_buffer->c_byte) {\n\t\t\t\tread_buffer->block = bytes;\n\t\t\t\tbytes += read_buffer->size;\n\t\t\t\tfile_bytes += read_buffer->size;\n\t\t\t\tcache_hash(read_buffer, read_buffer->block);\n\t\t\t\tif (block < thresh) {\n\t\t\t\t\tbuffer_list[block] = NULL;\n\t\t\t\t\tqueue_put(to_writer, read_buffer);\n\t\t\t\t} else\n\t\t\t\t\tbuffer_list[block] = read_buffer;\n\t\t\t} else {\n\t\t\t\tbuffer_list[block] = NULL;\n\t\t\t\tsparse += read_buffer->size;\n\t\t\t\tcache_block_put(read_buffer);\n\t\t\t}\n\t\t}\n\t\tinc_progress_bar();\n\n\t\tif (++block < blocks) {\n\t\t\tread_buffer = get_file_buffer();\n\t\t\tif (read_buffer->error)\n\t\t\t\tgoto read_err;\n\t\t}\n\t}\n\n\tdupl_ptr = duplicate(read_size, file_bytes, &block_listp, &dup_start, &fragment, fragment_buffer, blocks, 0, FALSE);\n\n\tif (dupl_ptr) {\n\t\t*duplicate_file = FALSE;\n\t\tfor (block = thresh; block < blocks; block++)\n\t\t\tif (buffer_list[block])\n\t\t\t\tqueue_put(to_writer, buffer_list[block]);\n\t\tfragment = get_and_fill_fragment(fragment_buffer, dir_ent);\n\t\tdupl_ptr->fragment = fragment;\n\t} else {\n\t\t*duplicate_file = TRUE;\n\t\tfor (block = thresh; block < blocks; block++)\n\t\t\tcache_block_put(buffer_list[block]);\n\t\tbytes = start;\n\t\tif (thresh && !block_device) {\n\t\t\tint res;\n\n\t\t\tqueue_put(to_writer, NULL);\n\t\t\tif (queue_get(from_writer) != 0)\n\t\t\t\tEXIT_MKSQUASHFS();\n\t\t\tres = ftruncate(fd, bytes);\n\t\t\tif (res != 0)\n\t\t\t\tBAD_ERROR(\"Failed to truncate dest file because\" \"  %s\\n\", strerror(errno));\n\t\t}\n\t}\n\n\tunlock_fragments();\n\tcache_block_put(fragment_buffer);\n\tfree(buffer_list);\n\tfile_count++;\n\ttotal_bytes += read_size;\n\n\t/*\n\t * sparse count is needed to ensure squashfs correctly reports a\n\t * a smaller block count on stat calls to sparse files.  This is\n\t * to ensure intelligent applications like cp correctly handle the\n\t * file as a sparse file.  If the file in the original filesystem isn't\n\t * stored as a sparse file then still store it sparsely in squashfs, but\n\t * report it as non-sparse on stat calls to preserve semantics\n\t */\n\tif (sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size)\n\t\tsparse = 0;\n\n\tcreate_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, read_size, dup_start, blocks, block_listp, fragment, NULL, sparse);\n\n\tif (*duplicate_file == TRUE)\n\t\tfree(block_list);\n\n\treturn 0;\n\n read_err:\n\tdec_progress_bar(block);\n\tstatus = read_buffer->error;\n\tbytes = start;\n\tif (thresh && !block_device) {\n\t\tint res;\n\n\t\tqueue_put(to_writer, NULL);\n\t\tif (queue_get(from_writer) != 0)\n\t\t\tEXIT_MKSQUASHFS();\n\t\tres = ftruncate(fd, bytes);\n\t\tif (res != 0)\n\t\t\tBAD_ERROR(\"Failed to truncate dest file because %s\\n\", strerror(errno));\n\t}\n\tunlock_fragments();\n\tfor (blocks = thresh; blocks < block; blocks++)\n\t\tcache_block_put(buffer_list[blocks]);\n\tfree(buffer_list);\n\tfree(block_list);\n\tcache_block_put(read_buffer);\n\treturn status;\n}\n\nint write_file_blocks(squashfs_inode * inode, struct dir_ent *dir_ent, struct file_buffer *read_buffer, int *dup) {\n\tlong long read_size = read_buffer->file_size;\n\tlong long file_bytes, start;\n\tstruct fragment *fragment;\n\tunsigned int *block_list;\n\tint block, status;\n\tint blocks = (read_size + block_size - 1) >> block_log;\n\tlong long sparse = 0;\n\tstruct file_buffer *fragment_buffer = NULL;\n\n\tif (pre_duplicate(read_size))\n\t\treturn write_file_blocks_dup(inode, dir_ent, read_buffer, dup);\n\n\t*dup = FALSE;\n\n\tblock_list = malloc(blocks * sizeof(unsigned int));\n\tif (block_list == NULL)\n\t\tMEM_ERROR();\n\n\tlock_fragments();\n\n\tfile_bytes = 0;\n\tstart = bytes;\n\tfor (block = 0; block < blocks;) {\n\t\tif (read_buffer->fragment) {\n\t\t\tblock_list[block] = 0;\n\t\t\tfragment_buffer = read_buffer;\n\t\t\tblocks = read_size >> block_log;\n\t\t} else {\n\t\t\tblock_list[block] = read_buffer->c_byte;\n\t\t\tif (read_buffer->c_byte) {\n\t\t\t\tread_buffer->block = bytes;\n\t\t\t\tbytes += read_buffer->size;\n\t\t\t\tcache_hash(read_buffer, read_buffer->block);\n\t\t\t\tfile_bytes += read_buffer->size;\n\t\t\t\tqueue_put(to_writer, read_buffer);\n\t\t\t} else {\n\t\t\t\tsparse += read_buffer->size;\n\t\t\t\tcache_block_put(read_buffer);\n\t\t\t}\n\t\t}\n\t\tinc_progress_bar();\n\n\t\tif (++block < blocks) {\n\t\t\tread_buffer = get_file_buffer();\n\t\t\tif (read_buffer->error)\n\t\t\t\tgoto read_err;\n\t\t}\n\t}\n\n\tunlock_fragments();\n\tfragment = get_and_fill_fragment(fragment_buffer, dir_ent);\n\n\tif (duplicate_checking)\n\t\tadd_non_dup(read_size, file_bytes, block_list, start, fragment, 0, fragment_buffer ? fragment_buffer->checksum : 0, FALSE, TRUE);\n\tcache_block_put(fragment_buffer);\n\tfile_count++;\n\ttotal_bytes += read_size;\n\n\t/*\n\t * sparse count is needed to ensure squashfs correctly reports a\n\t * a smaller block count on stat calls to sparse files.  This is\n\t * to ensure intelligent applications like cp correctly handle the\n\t * file as a sparse file.  If the file in the original filesystem isn't\n\t * stored as a sparse file then still store it sparsely in squashfs, but\n\t * report it as non-sparse on stat calls to preserve semantics\n\t */\n\tif (sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size)\n\t\tsparse = 0;\n\n\tcreate_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL, sparse);\n\n\tif (duplicate_checking == FALSE) {\n\t\tfree(block_list);\n\t\tfree_fragment(fragment);\n\t}\n\n\treturn 0;\n\n read_err:\n\tdec_progress_bar(block);\n\tstatus = read_buffer->error;\n\tbytes = start;\n\tif (!block_device) {\n\t\tint res;\n\n\t\tqueue_put(to_writer, NULL);\n\t\tif (queue_get(from_writer) != 0)\n\t\t\tEXIT_MKSQUASHFS();\n\t\tres = ftruncate(fd, bytes);\n\t\tif (res != 0)\n\t\t\tBAD_ERROR(\"Failed to truncate dest file because %s\\n\", strerror(errno));\n\t}\n\tunlock_fragments();\n\tfree(block_list);\n\tcache_block_put(read_buffer);\n\treturn status;\n}\n\nvoid write_file(squashfs_inode * inode, struct dir_ent *dir, int *dup) {\n\tint status;\n\tstruct file_buffer *read_buffer;\n\n again:\n\tread_buffer = get_file_buffer();\n\tstatus = read_buffer->error;\n\n\tif (status)\n\t\tcache_block_put(read_buffer);\n\telse if (read_buffer->file_size == -1)\n\t\tstatus = write_file_process(inode, dir, read_buffer, dup);\n\telse if (read_buffer->file_size == 0)\n\t\twrite_file_empty(inode, dir, read_buffer, dup);\n\telse if (read_buffer->fragment && read_buffer->c_byte)\n\t\twrite_file_frag(inode, dir, read_buffer, dup);\n\telse\n\t\tstatus = write_file_blocks(inode, dir, read_buffer, dup);\n\n\tif (status == 2) {\n\t\tERROR(\"File %s changed size while reading filesystem, \" \"attempting to re-read\\n\", pathname(dir));\n\t\tgoto again;\n\t} else if (status == 1) {\n\t\tERROR_START(\"Failed to read file %s\", pathname(dir));\n\t\tERROR_EXIT(\", creating empty file\\n\");\n\t\twrite_file_empty(inode, dir, NULL, dup);\n\t}\n}\n\n#define BUFF_SIZE 512\nchar *name;\nchar *basename_r();\n\nchar *getbase(char *pathname) {\n\tstatic char *b_buffer = NULL;\n\tstatic int b_size = BUFF_SIZE;\n\tchar *result;\n\n\tif (b_buffer == NULL) {\n\t\tb_buffer = malloc(b_size);\n\t\tif (b_buffer == NULL)\n\t\t\tMEM_ERROR();\n\t}\n\n\twhile (1) {\n\t\tif (*pathname != '/') {\n\t\t\tresult = getcwd(b_buffer, b_size);\n\t\t\tif (result == NULL && errno != ERANGE)\n\t\t\t\tBAD_ERROR(\"Getcwd failed in getbase\\n\");\n\n\t\t\t/* enough room for pathname + \"/\" + '\\0' terminator? */\n\t\t\tif (result && strlen(pathname) + 2 <= b_size - strlen(b_buffer)) {\n\t\t\t\tstrcat(strcat(b_buffer, \"/\"), pathname);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else if (strlen(pathname) < b_size) {\n\t\t\tstrcpy(b_buffer, pathname);\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Buffer not large enough, realloc and try again */\n\t\tb_buffer = realloc(b_buffer, b_size += BUFF_SIZE);\n\t\tif (b_buffer == NULL)\n\t\t\tMEM_ERROR();\n\t}\n\n\tname = b_buffer;\n\tif (((result = basename_r()) == NULL) || (strcmp(result, \"..\") == 0))\n\t\treturn NULL;\n\telse\n\t\treturn result;\n}\n\nchar *basename_r() {\n\tchar *s;\n\tchar *p;\n\tint n = 1;\n\n\tfor (;;) {\n\t\ts = name;\n\t\tif (*name == '\\0')\n\t\t\treturn NULL;\n\t\tif (*name != '/') {\n\t\t\twhile (*name != '\\0' && *name != '/')\n\t\t\t\tname++;\n\t\t\tn = name - s;\n\t\t}\n\t\twhile (*name == '/')\n\t\t\tname++;\n\t\tif (strncmp(s, \".\", n) == 0)\n\t\t\tcontinue;\n\t\tif ((*name == '\\0') || (strncmp(s, \"..\", n) == 0) || ((p = basename_r()) == NULL)) {\n\t\t\ts[n] = '\\0';\n\t\t\treturn s;\n\t\t}\n\t\tif (strcmp(p, \"..\") == 0)\n\t\t\tcontinue;\n\t\treturn p;\n\t}\n}\n\nstruct inode_info *lookup_inode2(struct stat *buf, int pseudo, int id) {\n\tint ino_hash = INODE_HASH(buf->st_dev, buf->st_ino);\n\tstruct inode_info *inode;\n\n\t/*\n\t * Look-up inode in hash table, if it already exists we have a\n\t * hard-link, so increment the nlink count and return it.\n\t * Don't do the look-up for directories because we don't hard-link\n\t * directories.\n\t */\n\tif ((buf->st_mode & S_IFMT) != S_IFDIR) {\n\t\tfor (inode = inode_info[ino_hash]; inode; inode = inode->next) {\n\t\t\tif (memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) {\n\t\t\t\tinode->nlink++;\n\t\t\t\treturn inode;\n\t\t\t}\n\t\t}\n\t}\n\n\tinode = malloc(sizeof(struct inode_info));\n\tif (inode == NULL)\n\t\tMEM_ERROR();\n\n\tmemcpy(&inode->buf, buf, sizeof(struct stat));\n\tinode->read = FALSE;\n\tinode->root_entry = FALSE;\n\tinode->pseudo_file = pseudo;\n\tinode->pseudo_id = id;\n\tinode->inode = SQUASHFS_INVALID_BLK;\n\tinode->nlink = 1;\n\tinode->inode_number = 0;\n\n\t/*\n\t * Copy filesystem wide defaults into inode, these filesystem\n\t * wide defaults may be altered on an individual inode basis by\n\t * user specified actions\n\t *\n\t */\n\tinode->no_fragments = no_fragments;\n\tinode->always_use_fragments = always_use_fragments;\n\tinode->noD = noD;\n\tinode->noF = noF;\n\n\tif ((buf->st_mode & S_IFMT) == S_IFREG)\n\t\tprogress_bar_size((buf->st_size + block_size - 1) >> block_log);\n\n\tinode->next = inode_info[ino_hash];\n\tinode_info[ino_hash] = inode;\n\n\treturn inode;\n}\n\ninline struct inode_info *lookup_inode(struct stat *buf) {\n\treturn lookup_inode2(buf, 0, 0);\n}\n\ninline void alloc_inode_no(struct inode_info *inode, unsigned int use_this) {\n\tif (inode->inode_number == 0)\n\t\tinode->inode_number = use_this ? : inode_no++;\n}\n\ninline struct dir_ent *create_dir_entry(char *name, char *source_name, char *nonstandard_pathname, struct dir_info *dir) {\n\tstruct dir_ent *dir_ent = malloc(sizeof(struct dir_ent));\n\tif (dir_ent == NULL)\n\t\tMEM_ERROR();\n\n\tdir_ent->name = name;\n\tdir_ent->source_name = source_name;\n\tdir_ent->nonstandard_pathname = nonstandard_pathname;\n\tdir_ent->our_dir = dir;\n\tdir_ent->next = NULL;\n\n\treturn dir_ent;\n}\n\ninline void add_dir_entry(struct dir_ent *dir_ent, struct dir_info *sub_dir, struct inode_info *inode_info) {\n\tstruct dir_info *dir = dir_ent->our_dir;\n\n\tif (sub_dir)\n\t\tsub_dir->dir_ent = dir_ent;\n\tdir_ent->inode = inode_info;\n\tdir_ent->dir = sub_dir;\n\n\tdir_ent->next = dir->list;\n\tdir->list = dir_ent;\n\tdir->count++;\n}\n\ninline void add_dir_entry2(char *name, char *source_name, char *nonstandard_pathname, struct dir_info *sub_dir, struct inode_info *inode_info, struct dir_info *dir) {\n\tstruct dir_ent *dir_ent = create_dir_entry(name, source_name,\n\t\t\t\t\t\t\t\t\t\t\t   nonstandard_pathname, dir);\n\n\tadd_dir_entry(dir_ent, sub_dir, inode_info);\n}\n\ninline void free_dir_entry(struct dir_ent *dir_ent) {\n\tif (dir_ent->name)\n\t\tfree(dir_ent->name);\n\n\tif (dir_ent->source_name)\n\t\tfree(dir_ent->source_name);\n\n\tfree(dir_ent);\n}\n\ninline void add_excluded(struct dir_info *dir) {\n\tdir->excluded++;\n}\n\nvoid dir_scan(squashfs_inode * inode, char *pathname, struct dir_ent *(_readdir) (struct dir_info *), int progress) {\n\tstruct stat buf;\n\tstruct dir_info *dir_info = dir_scan1(pathname, \"\", paths, _readdir, 1);\n\tstruct dir_ent *dir_ent;\n\n\tif (dir_info == NULL)\n\t\treturn;\n\n\t/*\n\t * Process most actions and any pseudo files\n\t */\n\tif (actions() || get_pseudo())\n\t\tdir_scan2(dir_info, get_pseudo());\n\n\t/*\n\t * Process move actions\n\t */\n\tif (move_actions()) {\n\t\tdir_scan3(dir_info, dir_info);\n\t\tdo_move_actions();\n\t}\n\n\t/*\n\t * Process empty actions\n\t */\n\tif (empty_actions())\n\t\tdir_scan4(dir_info);\n\n\t/*\n\t * Sort directories and compute the inode numbers\n\t */\n\tdir_scan5(dir_info);\n\n\tdir_ent = create_dir_entry(\"\", NULL, pathname, scan1_opendir(\"\", \"\", 0));\n\n\tif (pathname[0] == '\\0') {\n\t\t/*\n\t\t * dummy top level directory, if multiple sources specified on\n\t\t * command line\n\t\t */\n\t\tmemset(&buf, 0, sizeof(buf));\n\t\tbuf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR;\n\t\tbuf.st_uid = getuid();\n\t\tbuf.st_gid = getgid();\n\t\tbuf.st_mtime = time(NULL);\n\t\tbuf.st_dev = 0;\n\t\tbuf.st_ino = 0;\n\t\tdir_ent->inode = lookup_inode2(&buf, PSEUDO_FILE_OTHER, 0);\n\t} else {\n\t\tif (lstat(pathname, &buf) == -1)\n\t\t\t/* source directory has disappeared? */\n\t\t\tBAD_ERROR(\"Cannot stat source directory %s because %s\\n\", pathname, strerror(errno));\n\t\tdir_ent->inode = lookup_inode(&buf);\n\t}\n\n\talloc_inode_no(dir_ent->inode, root_inode_number);\n\tdir_ent->dir = dir_info;\n\tdir_info->dir_ent = dir_ent;\n\n\teval_actions(dir_ent);\n\n\tif (sorted)\n\t\tgenerate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf);\n\n\tif (appending) {\n\t\tsigset_t sigmask;\n\n\t\trestore_thread = init_restore_thread();\n\t\tsigemptyset(&sigmask);\n\t\tsigaddset(&sigmask, SIGINT);\n\t\tsigaddset(&sigmask, SIGTERM);\n\t\tsigaddset(&sigmask, SIGUSR1);\n\t\tif (pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == -1)\n\t\t\tBAD_ERROR(\"Failed to set signal mask\\n\");\n\t\twrite_destination(fd, SQUASHFS_START, 4, \"\\0\\0\\0\\0\");\n\t}\n\n\tqueue_put(to_reader, dir_info);\n\n\tif (sorted)\n\t\tsort_files_and_write(dir_info);\n\n\tset_progressbar_state(progress);\n\tdir_scan6(inode, dir_info);\n\tdir_ent->inode->inode = *inode;\n\tdir_ent->inode->type = SQUASHFS_DIR_TYPE;\n}\n\n/*\n * dir_scan1 routines...\n * These scan the source directories into memory for processing.\n * Exclude actions are processed here (in contrast to the other actions)\n * because they affect what is scanned.\n */\nstruct dir_info *scan1_opendir(char *pathname, char *subpath, int depth) {\n\tstruct dir_info *dir;\n\n\tdir = malloc(sizeof(struct dir_info));\n\tif (dir == NULL)\n\t\tMEM_ERROR();\n\n\tif (pathname[0] != '\\0') {\n\t\tdir->linuxdir = opendir(pathname);\n\t\tif (dir->linuxdir == NULL) {\n\t\t\tfree(dir);\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\tdir->pathname = strdup(pathname);\n\tdir->subpath = strdup(subpath);\n\tdir->count = 0;\n\tdir->directory_count = 0;\n\tdir->dir_is_ldir = TRUE;\n\tdir->list = NULL;\n\tdir->depth = depth;\n\tdir->excluded = 0;\n\n\treturn dir;\n}\n\nstruct dir_ent *scan1_encomp_readdir(struct dir_info *dir) {\n\tstatic int index = 0;\n\n\tif (dir->count < old_root_entries) {\n\t\tint i;\n\n\t\tfor (i = 0; i < old_root_entries; i++) {\n\t\t\tif (old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE)\n\t\t\t\tdir->directory_count++;\n\t\t\tadd_dir_entry2(old_root_entry[i].name, NULL, NULL, NULL, &old_root_entry[i].inode, dir);\n\t\t}\n\t}\n\n\twhile (index < source) {\n\t\tchar *basename = NULL;\n\t\tchar *dir_name = getbase(source_path[index]);\n\t\tint pass = 1, res;\n\n\t\tif (dir_name == NULL) {\n\t\t\tERROR_START(\"Bad source directory %s\", source_path[index]);\n\t\t\tERROR_EXIT(\" - skipping ...\\n\");\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tdir_name = strdup(dir_name);\n\t\tfor (;;) {\n\t\t\tstruct dir_ent *dir_ent = dir->list;\n\n\t\t\tfor (; dir_ent && strcmp(dir_ent->name, dir_name) != 0; dir_ent = dir_ent->next) ;\n\t\t\tif (dir_ent == NULL)\n\t\t\t\tbreak;\n\t\t\tERROR(\"Source directory entry %s already used! - trying\" \" \", dir_name);\n\t\t\tif (pass == 1)\n\t\t\t\tbasename = dir_name;\n\t\t\telse\n\t\t\t\tfree(dir_name);\n\t\t\tres = asprintf(&dir_name, \"%s_%d\", basename, pass++);\n\t\t\tif (res == -1)\n\t\t\t\tBAD_ERROR(\"asprintf failed in \" \"scan1_encomp_readdir\\n\");\n\t\t\tERROR(\"%s\\n\", dir_name);\n\t\t}\n\t\treturn create_dir_entry(dir_name, basename, source_path[index++], dir);\n\t}\n\treturn NULL;\n}\n\nstruct dir_ent *scan1_single_readdir(struct dir_info *dir) {\n\tstruct dirent *d_name;\n\tint i;\n\n\tif (dir->count < old_root_entries) {\n\t\tfor (i = 0; i < old_root_entries; i++) {\n\t\t\tif (old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE)\n\t\t\t\tdir->directory_count++;\n\t\t\tadd_dir_entry2(old_root_entry[i].name, NULL, NULL, NULL, &old_root_entry[i].inode, dir);\n\t\t}\n\t}\n\n\tif ((d_name = readdir(dir->linuxdir)) != NULL) {\n\t\tchar *basename = NULL;\n\t\tchar *dir_name = strdup(d_name->d_name);\n\t\tint pass = 1, res;\n\n\t\tfor (;;) {\n\t\t\tstruct dir_ent *dir_ent = dir->list;\n\n\t\t\tfor (; dir_ent && strcmp(dir_ent->name, dir_name) != 0; dir_ent = dir_ent->next) ;\n\t\t\tif (dir_ent == NULL)\n\t\t\t\tbreak;\n\t\t\tERROR(\"Source directory entry %s already used! - trying\" \" \", dir_name);\n\t\t\tif (pass == 1)\n\t\t\t\tbasename = dir_name;\n\t\t\telse\n\t\t\t\tfree(dir_name);\n\t\t\tres = asprintf(&dir_name, \"%s_%d\", d_name->d_name, pass++);\n\t\t\tif (res == -1)\n\t\t\t\tBAD_ERROR(\"asprintf failed in \" \"scan1_single_readdir\\n\");\n\t\t\tERROR(\"%s\\n\", dir_name);\n\t\t}\n\t\treturn create_dir_entry(dir_name, basename, NULL, dir);\n\t}\n\n\treturn NULL;\n}\n\nstruct dir_ent *scan1_readdir(struct dir_info *dir) {\n\tstruct dirent *d_name = readdir(dir->linuxdir);\n\n\treturn d_name ? create_dir_entry(strdup(d_name->d_name), NULL, NULL, dir) : NULL;\n}\n\nvoid scan1_freedir(struct dir_info *dir) {\n\tif (dir->pathname[0] != '\\0')\n\t\tclosedir(dir->linuxdir);\n}\n\nstruct dir_info *dir_scan1(char *filename, char *subpath, struct pathnames *paths, struct dir_ent *(_readdir) (struct dir_info *), int depth) {\n\tstruct dir_info *dir = scan1_opendir(filename, subpath, depth);\n\tstruct dir_ent *dir_ent;\n\n\tif (dir == NULL) {\n\t\tERROR_START(\"Could not open %s\", filename);\n\t\tERROR_EXIT(\", skipping...\\n\");\n\t\treturn NULL;\n\t}\n\n\twhile ((dir_ent = _readdir(dir))) {\n\t\tstruct dir_info *sub_dir;\n\t\tstruct stat buf;\n\t\tstruct pathnames *new = NULL;\n\t\tchar *filename = pathname(dir_ent);\n\t\tchar *subpath = NULL;\n\t\tchar *dir_name = dir_ent->name;\n\n\t\tif (strcmp(dir_name, \".\") == 0 || strcmp(dir_name, \"..\") == 0) {\n\t\t\tfree_dir_entry(dir_ent);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (lstat(filename, &buf) == -1) {\n\t\t\tERROR_START(\"Cannot stat dir/file %s because %s\", filename, strerror(errno));\n\t\t\tERROR_EXIT(\", ignoring\\n\");\n\t\t\tfree_dir_entry(dir_ent);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ((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) {\n\t\t\tERROR_START(\"File %s has unrecognised filetype %d\", filename, buf.st_mode & S_IFMT);\n\t\t\tERROR_EXIT(\", ignoring\\n\");\n\t\t\tfree_dir_entry(dir_ent);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ((old_exclude && old_excluded(filename, &buf)) || (!old_exclude && excluded(dir_name, paths, &new))) {\n\t\t\tadd_excluded(dir);\n\t\t\tfree_dir_entry(dir_ent);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (exclude_actions()) {\n\t\t\tsubpath = subpathname(dir_ent);\n\n\t\t\tif (eval_exclude_actions(dir_name, filename, subpath, &buf, depth)) {\n\t\t\t\tadd_excluded(dir);\n\t\t\t\tfree_dir_entry(dir_ent);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif ((buf.st_mode & S_IFMT) == S_IFDIR) {\n\t\t\tif (subpath == NULL)\n\t\t\t\tsubpath = subpathname(dir_ent);\n\n\t\t\tsub_dir = dir_scan1(filename, subpath, new, scan1_readdir, depth + 1);\n\t\t\tif (sub_dir == NULL) {\n\t\t\t\tfree_dir_entry(dir_ent);\n\t\t\t\tfree(new);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tdir->directory_count++;\n\t\t} else\n\t\t\tsub_dir = NULL;\n\n\t\tadd_dir_entry(dir_ent, sub_dir, lookup_inode(&buf));\n\t\tfree(new);\n\t}\n\n\tscan1_freedir(dir);\n\n\treturn dir;\n}\n\n/*\n * dir_scan2 routines...\n * This processes most actions and any pseudo files\n */\nstruct dir_ent *scan2_readdir(struct dir_info *dir, struct dir_ent *dir_ent) {\n\tif (dir_ent == NULL)\n\t\tdir_ent = dir->list;\n\telse\n\t\tdir_ent = dir_ent->next;\n\n\tfor (; dir_ent && dir_ent->inode->root_entry; dir_ent = dir_ent->next) ;\n\n\treturn dir_ent;\n}\n\nstruct dir_ent *scan2_lookup(struct dir_info *dir, char *name) {\n\tstruct dir_ent *dir_ent = dir->list;\n\n\tfor (; dir_ent && strcmp(dir_ent->name, name) != 0; dir_ent = dir_ent->next) ;\n\n\treturn dir_ent;\n}\n\nvoid dir_scan2(struct dir_info *dir, struct pseudo *pseudo) {\n\tstruct dir_ent *dir_ent = NULL;\n\tstruct pseudo_entry *pseudo_ent;\n\tstruct stat buf;\n\tstatic int pseudo_ino = 1;\n\n\twhile ((dir_ent = scan2_readdir(dir, dir_ent)) != NULL) {\n\t\tstruct inode_info *inode_info = dir_ent->inode;\n\t\tstruct stat *buf = &inode_info->buf;\n\t\tchar *name = dir_ent->name;\n\n\t\teval_actions(dir_ent);\n\n\t\tif ((buf->st_mode & S_IFMT) == S_IFDIR)\n\t\t\tdir_scan2(dir_ent->dir, pseudo_subdir(name, pseudo));\n\t}\n\n\twhile ((pseudo_ent = pseudo_readdir(pseudo)) != NULL) {\n\t\tdir_ent = scan2_lookup(dir, pseudo_ent->name);\n\t\tif (pseudo_ent->dev->type == 'm') {\n\t\t\tstruct stat *buf;\n\t\t\tif (dir_ent == NULL) {\n\t\t\t\tERROR_START(\"Pseudo modify file \\\"%s\\\" does \" \"not exist in source filesystem.\", pseudo_ent->pathname);\n\t\t\t\tERROR_EXIT(\"  Ignoring.\\n\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (dir_ent->inode->root_entry) {\n\t\t\t\tERROR_START(\"Pseudo modify file \\\"%s\\\" is a \" \"pre-existing file in the filesystem \" \"being appended to.  It cannot be \" \"modified.\", pseudo_ent->pathname);\n\t\t\t\tERROR_EXIT(\"  Ignoring.\\n\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbuf = &dir_ent->inode->buf;\n\t\t\tbuf->st_mode = (buf->st_mode & S_IFMT) | pseudo_ent->dev->mode;\n\t\t\tbuf->st_uid = pseudo_ent->dev->uid;\n\t\t\tbuf->st_gid = pseudo_ent->dev->gid;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (dir_ent) {\n\t\t\tif (dir_ent->inode->root_entry) {\n\t\t\t\tERROR_START(\"Pseudo file \\\"%s\\\" is a \" \"pre-existing file in the filesystem \" \"being appended to.\", pseudo_ent->pathname);\n\t\t\t\tERROR_EXIT(\"  Ignoring.\\n\");\n\t\t\t} else {\n\t\t\t\tERROR_START(\"Pseudo file \\\"%s\\\" exists in \" \"source filesystem \\\"%s\\\".\", pseudo_ent->pathname, pathname(dir_ent));\n\t\t\t\tERROR_EXIT(\"\\nIgnoring, exclude it (-e/-ef) to \" \"override.\\n\");\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tmemset(&buf, 0, sizeof(buf));\n\t\tbuf.st_mode = pseudo_ent->dev->mode;\n\t\tbuf.st_uid = pseudo_ent->dev->uid;\n\t\tbuf.st_gid = pseudo_ent->dev->gid;\n\t\tbuf.st_rdev = makedev(pseudo_ent->dev->major, pseudo_ent->dev->minor);\n\t\tbuf.st_mtime = time(NULL);\n\t\tbuf.st_ino = pseudo_ino++;\n\n\t\tif (pseudo_ent->dev->type == 'd') {\n\t\t\tstruct dir_ent *dir_ent = create_dir_entry(pseudo_ent->name, NULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   pseudo_ent->pathname, dir);\n\t\t\tchar *subpath = strdup(subpathname(dir_ent));\n\t\t\tstruct dir_info *sub_dir = scan1_opendir(\"\", subpath,\n\t\t\t\t\t\t\t\t\t\t\t\t\t dir->depth + 1);\n\t\t\tif (sub_dir == NULL) {\n\t\t\t\tERROR_START(\"Could not create pseudo directory \" \"\\\"%s\\\"\", pseudo_ent->pathname);\n\t\t\t\tERROR_EXIT(\", skipping...\\n\");\n\t\t\t\tfree(subpath);\n\t\t\t\tpseudo_ino--;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tdir_scan2(sub_dir, pseudo_ent->pseudo);\n\t\t\tdir->directory_count++;\n\t\t\tadd_dir_entry(dir_ent, sub_dir, lookup_inode2(&buf, PSEUDO_FILE_OTHER, 0));\n\t\t} else if (pseudo_ent->dev->type == 'f') {\n\t\t\tadd_dir_entry2(pseudo_ent->name, NULL, pseudo_ent->pathname, NULL, lookup_inode2(&buf, PSEUDO_FILE_PROCESS, pseudo_ent->dev->pseudo_id), dir);\n\t\t} else {\n\t\t\tadd_dir_entry2(pseudo_ent->name, NULL, pseudo_ent->pathname, NULL, lookup_inode2(&buf, PSEUDO_FILE_OTHER, 0), dir);\n\t\t}\n\t}\n}\n\n/*\n * dir_scan3 routines...\n * This processes the move action\n */\nvoid dir_scan3(struct dir_info *root, struct dir_info *dir) {\n\tstruct dir_ent *dir_ent = NULL;\n\n\twhile ((dir_ent = scan2_readdir(dir, dir_ent)) != NULL) {\n\n\t\teval_move_actions(root, dir_ent);\n\n\t\tif ((dir_ent->inode->buf.st_mode & S_IFMT) == S_IFDIR)\n\t\t\tdir_scan3(root, dir_ent->dir);\n\t}\n}\n\n/*\n * dir_scan4 routines...\n * This processes the empty action.  This action has to be processed after\n * all other actions because the previous exclude and move actions and the\n * pseudo actions affect whether a directory is empty\n */\nvoid dir_scan4(struct dir_info *dir) {\n\tstruct dir_ent *dir_ent = dir->list, *prev = NULL;\n\n\twhile (dir_ent) {\n\t\tif ((dir_ent->inode->buf.st_mode & S_IFMT) == S_IFDIR) {\n\t\t\tdir_scan4(dir_ent->dir);\n\n\t\t\tif (eval_empty_actions(dir_ent)) {\n\t\t\t\tstruct dir_ent *tmp = dir_ent;\n\n\t\t\t\t/*\n\t\t\t\t * delete sub-directory, this is by definition\n\t\t\t\t * empty\n\t\t\t\t */\n\t\t\t\tfree(dir_ent->dir->pathname);\n\t\t\t\tfree(dir_ent->dir->subpath);\n\t\t\t\tfree(dir_ent->dir);\n\n\t\t\t\t/* remove dir_ent from list */\n\t\t\t\tdir_ent = dir_ent->next;\n\t\t\t\tif (prev)\n\t\t\t\t\tprev->next = dir_ent;\n\t\t\t\telse\n\t\t\t\t\tdir->list = dir_ent;\n\n\t\t\t\t/* free it */\n\t\t\t\tfree_dir_entry(tmp);\n\n\t\t\t\t/* update counts */\n\t\t\t\tdir->directory_count--;\n\t\t\t\tdir->count--;\n\t\t\t\tadd_excluded(dir);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tprev = dir_ent;\n\t\tdir_ent = dir_ent->next;\n\t}\n}\n\n/*\n * dir_scan5 routines...\n * This sorts every directory and computes the inode numbers\n */\n\n/*\n * Bottom up linked list merge sort.\n *\n * Qsort and other O(n log n) algorithms work well with arrays but not\n * linked lists.  Merge sort another O(n log n) sort algorithm on the other hand\n * is not ideal for arrays (as it needs an additonal n storage locations\n * as sorting is not done in place), but it is ideal for linked lists because\n * it doesn't require any extra storage,\n */\nvoid sort_directory(struct dir_info *dir) {\n\tstruct dir_ent *cur, *l1, *l2, *next;\n\tint len1, len2, stride = 1;\n\n\tif (dir->list == NULL || dir->count < 2)\n\t\treturn;\n\n\t/*\n\t * We can consider our linked-list to be made up of stride length\n\t * sublists.  Eacn iteration around this loop merges adjacent\n\t * stride length sublists into larger 2*stride sublists.  We stop\n\t * when stride becomes equal to the entire list.\n\t *\n\t * Initially stride = 1 (by definition a sublist of 1 is sorted), and\n\t * these 1 element sublists are merged into 2 element sublists,  which\n\t * are then merged into 4 element sublists and so on.\n\t */\n\tdo {\n\t\tl2 = dir->list;\t\t\t/* head of current linked list */\n\t\tcur = NULL;\t\t\t\t/* empty output list */\n\n\t\t/*\n\t\t * Iterate through the linked list, merging adjacent sublists.\n\t\t * On each interation l2 points to the next sublist pair to be\n\t\t * merged (if there's only one sublist left this is simply added\n\t\t * to the output list)\n\t\t */\n\t\twhile (l2) {\n\t\t\tl1 = l2;\n\t\t\tfor (len1 = 0; l2 && len1 < stride; len1++, l2 = l2->next) ;\n\t\t\tlen2 = stride;\n\n\t\t\t/*\n\t\t\t * l1 points to first sublist.\n\t\t\t * l2 points to second sublist.\n\t\t\t * Merge them onto the output list\n\t\t\t */\n\t\t\twhile (len1 && l2 && len2) {\n\t\t\t\tif (strcmp(l1->name, l2->name) <= 0) {\n\t\t\t\t\tnext = l1;\n\t\t\t\t\tl1 = l1->next;\n\t\t\t\t\tlen1--;\n\t\t\t\t} else {\n\t\t\t\t\tnext = l2;\n\t\t\t\t\tl2 = l2->next;\n\t\t\t\t\tlen2--;\n\t\t\t\t}\n\n\t\t\t\tif (cur) {\n\t\t\t\t\tcur->next = next;\n\t\t\t\t\tcur = next;\n\t\t\t\t} else\n\t\t\t\t\tdir->list = cur = next;\n\t\t\t}\n\t\t\t/*\n\t\t\t * One sublist is now empty, copy the other one onto the\n\t\t\t * output list\n\t\t\t */\n\t\t\tfor (; len1; len1--, l1 = l1->next) {\n\t\t\t\tif (cur) {\n\t\t\t\t\tcur->next = l1;\n\t\t\t\t\tcur = l1;\n\t\t\t\t} else\n\t\t\t\t\tdir->list = cur = l1;\n\t\t\t}\n\t\t\tfor (; l2 && len2; len2--, l2 = l2->next) {\n\t\t\t\tif (cur) {\n\t\t\t\t\tcur->next = l2;\n\t\t\t\t\tcur = l2;\n\t\t\t\t} else\n\t\t\t\t\tdir->list = cur = l2;\n\t\t\t}\n\t\t}\n\t\tcur->next = NULL;\n\t\tstride = stride << 1;\n\t} while (stride < dir->count);\n}\n\nvoid dir_scan5(struct dir_info *dir) {\n\tstruct dir_ent *dir_ent;\n\tunsigned int byte_count = 0;\n\n\tsort_directory(dir);\n\n\tfor (dir_ent = dir->list; dir_ent; dir_ent = dir_ent->next) {\n\t\tbyte_count += strlen(dir_ent->name) + sizeof(struct squashfs_dir_entry);\n\n\t\tif (dir_ent->inode->root_entry)\n\t\t\tcontinue;\n\n\t\talloc_inode_no(dir_ent->inode, 0);\n\n\t\tif ((dir_ent->inode->buf.st_mode & S_IFMT) == S_IFDIR)\n\t\t\tdir_scan5(dir_ent->dir);\n\t}\n\n\tif ((dir->count < 257 && byte_count < SQUASHFS_METADATA_SIZE))\n\t\tdir->dir_is_ldir = FALSE;\n}\n\n/*\n * dir_scan6 routines...\n * This generates the filesystem metadata and writes it out to the destination\n */\nvoid scan6_init_dir(struct directory *dir) {\n\tdir->buff = malloc(SQUASHFS_METADATA_SIZE);\n\tif (dir->buff == NULL)\n\t\tMEM_ERROR();\n\n\tdir->size = SQUASHFS_METADATA_SIZE;\n\tdir->p = dir->index_count_p = dir->buff;\n\tdir->entry_count = 256;\n\tdir->entry_count_p = NULL;\n\tdir->index = NULL;\n\tdir->i_count = dir->i_size = 0;\n}\n\nstruct dir_ent *scan6_readdir(struct directory *dir, struct dir_info *dir_info, struct dir_ent *dir_ent) {\n\tif (dir_ent == NULL)\n\t\tdir_ent = dir_info->list;\n\telse\n\t\tdir_ent = dir_ent->next;\n\n\tfor (; dir_ent && dir_ent->inode->root_entry; dir_ent = dir_ent->next)\n\t\tadd_dir(dir_ent->inode->inode, dir_ent->inode->inode_number, dir_ent->name, dir_ent->inode->type, dir);\n\n\treturn dir_ent;\n}\n\nvoid scan6_freedir(struct directory *dir) {\n\tif (dir->index)\n\t\tfree(dir->index);\n\tfree(dir->buff);\n}\n\nvoid dir_scan6(squashfs_inode * inode, struct dir_info *dir_info) {\n\tint squashfs_type;\n\tint duplicate_file;\n\tstruct directory dir;\n\tstruct dir_ent *dir_ent = NULL;\n\n\tscan6_init_dir(&dir);\n\n\twhile ((dir_ent = scan6_readdir(&dir, dir_info, dir_ent)) != NULL) {\n\t\tstruct stat *buf = &dir_ent->inode->buf;\n\n\t\tupdate_info(dir_ent);\n\n\t\tif (dir_ent->inode->inode == SQUASHFS_INVALID_BLK) {\n\t\t\tswitch (buf->st_mode & S_IFMT) {\n\t\t\tcase S_IFREG:\n\t\t\t\tsquashfs_type = SQUASHFS_FILE_TYPE;\n\t\t\t\twrite_file(inode, dir_ent, &duplicate_file);\n\t\t\t\tINFO(\"file %s, uncompressed size %lld \" \"bytes %s\\n\", subpathname(dir_ent), (long long)buf->st_size, duplicate_file ? \"DUPLICATE\" : \"\");\n\t\t\t\tbreak;\n\n\t\t\tcase S_IFDIR:\n\t\t\t\tsquashfs_type = SQUASHFS_DIR_TYPE;\n\t\t\t\tdir_scan6(inode, dir_ent->dir);\n\t\t\t\tbreak;\n\n\t\t\tcase S_IFLNK:\n\t\t\t\tsquashfs_type = SQUASHFS_SYMLINK_TYPE;\n\t\t\t\tcreate_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0);\n\t\t\t\tINFO(\"symbolic link %s inode 0x%llx\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tsym_count++;\n\t\t\t\tbreak;\n\n\t\t\tcase S_IFCHR:\n\t\t\t\tsquashfs_type = SQUASHFS_CHRDEV_TYPE;\n\t\t\t\tcreate_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0);\n\t\t\t\tINFO(\"character device %s inode 0x%llx\" \"\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tdev_count++;\n\t\t\t\tbreak;\n\n\t\t\tcase S_IFBLK:\n\t\t\t\tsquashfs_type = SQUASHFS_BLKDEV_TYPE;\n\t\t\t\tcreate_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0);\n\t\t\t\tINFO(\"block device %s inode 0x%llx\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tdev_count++;\n\t\t\t\tbreak;\n\n\t\t\tcase S_IFIFO:\n\t\t\t\tsquashfs_type = SQUASHFS_FIFO_TYPE;\n\t\t\t\tcreate_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0);\n\t\t\t\tINFO(\"fifo %s inode 0x%llx\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tfifo_count++;\n\t\t\t\tbreak;\n\n\t\t\tcase S_IFSOCK:\n\t\t\t\tsquashfs_type = SQUASHFS_SOCKET_TYPE;\n\t\t\t\tcreate_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0);\n\t\t\t\tINFO(\"unix domain socket %s inode \" \"0x%llx\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tsock_count++;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tBAD_ERROR(\"%s unrecognised file type, \" \"mode is %x\\n\", subpathname(dir_ent), buf->st_mode);\n\t\t\t}\n\t\t\tdir_ent->inode->inode = *inode;\n\t\t\tdir_ent->inode->type = squashfs_type;\n\t\t} else {\n\t\t\t*inode = dir_ent->inode->inode;\n\t\t\tsquashfs_type = dir_ent->inode->type;\n\t\t\tswitch (squashfs_type) {\n\t\t\tcase SQUASHFS_FILE_TYPE:\n\t\t\t\tif (!sorted)\n\t\t\t\t\tINFO(\"file %s, uncompressed \" \"size %lld bytes LINK\" \"\\n\", subpathname(dir_ent), (long long)\n\t\t\t\t\t\t buf->st_size);\n\t\t\t\tbreak;\n\t\t\tcase SQUASHFS_SYMLINK_TYPE:\n\t\t\t\tINFO(\"symbolic link %s inode 0x%llx \" \"LINK\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tbreak;\n\t\t\tcase SQUASHFS_CHRDEV_TYPE:\n\t\t\t\tINFO(\"character device %s inode 0x%llx \" \"LINK\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tbreak;\n\t\t\tcase SQUASHFS_BLKDEV_TYPE:\n\t\t\t\tINFO(\"block device %s inode 0x%llx \" \"LINK\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tbreak;\n\t\t\tcase SQUASHFS_FIFO_TYPE:\n\t\t\t\tINFO(\"fifo %s inode 0x%llx LINK\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tbreak;\n\t\t\tcase SQUASHFS_SOCKET_TYPE:\n\t\t\t\tINFO(\"unix domain socket %s inode \" \"0x%llx LINK\\n\", subpathname(dir_ent), *inode);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tadd_dir(*inode, get_inode_no(dir_ent->inode), dir_ent->name, squashfs_type, &dir);\n\t}\n\n\twrite_dir(inode, dir_info, &dir);\n\tINFO(\"directory %s inode 0x%llx\\n\", subpathname(dir_info->dir_ent), *inode);\n\n\tscan6_freedir(&dir);\n}\n\nunsigned int slog(unsigned int block) {\n\tint i;\n\n\tfor (i = 12; i <= 20; i++)\n\t\tif (block == (1 << i))\n\t\t\treturn i;\n\treturn 0;\n}\n\nint old_excluded(char *filename, struct stat *buf) {\n\tint i;\n\n\tfor (i = 0; i < exclude; i++)\n\t\tif ((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino))\n\t\t\treturn TRUE;\n\treturn FALSE;\n}\n\n#define ADD_ENTRY(buf) \\\n\tif(exclude % EXCLUDE_SIZE == 0) { \\\n\t\texclude_paths = realloc(exclude_paths, (exclude + EXCLUDE_SIZE) \\\n\t\t\t* sizeof(struct exclude_info)); \\\n\t\tif(exclude_paths == NULL) \\\n\t\t\tMEM_ERROR(); \\\n\t} \\\n\texclude_paths[exclude].st_dev = buf.st_dev; \\\n\texclude_paths[exclude++].st_ino = buf.st_ino;\nint old_add_exclude(char *path) {\n\tint i;\n\tchar *filename;\n\tstruct stat buf;\n\n\tif (path[0] == '/' || strncmp(path, \"./\", 2) == 0 || strncmp(path, \"../\", 3) == 0) {\n\t\tif (lstat(path, &buf) == -1) {\n\t\t\tERROR_START(\"Cannot stat exclude dir/file %s because \" \"%s\", path, strerror(errno));\n\t\t\tERROR_EXIT(\", ignoring\\n\");\n\t\t\treturn TRUE;\n\t\t}\n\t\tADD_ENTRY(buf);\n\t\treturn TRUE;\n\t}\n\n\tfor (i = 0; i < source; i++) {\n\t\tint res = asprintf(&filename, \"%s/%s\", source_path[i], path);\n\t\tif (res == -1)\n\t\t\tBAD_ERROR(\"asprintf failed in old_add_exclude\\n\");\n\t\tif (lstat(filename, &buf) == -1) {\n\t\t\tif (!(errno == ENOENT || errno == ENOTDIR)) {\n\t\t\t\tERROR_START(\"Cannot stat exclude dir/file %s \" \"because %s\", filename, strerror(errno));\n\t\t\t\tERROR_EXIT(\", ignoring\\n\");\n\t\t\t}\n\t\t\tfree(filename);\n\t\t\tcontinue;\n\t\t}\n\t\tfree(filename);\n\t\tADD_ENTRY(buf);\n\t}\n\treturn TRUE;\n}\n\nvoid add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) {\n\told_root_entry = realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1));\n\tif (old_root_entry == NULL)\n\t\tMEM_ERROR();\n\n\told_root_entry[old_root_entries].name = strdup(name);\n\told_root_entry[old_root_entries].inode.inode = inode;\n\told_root_entry[old_root_entries].inode.inode_number = inode_number;\n\told_root_entry[old_root_entries].inode.type = type;\n\told_root_entry[old_root_entries++].inode.root_entry = TRUE;\n}\n\nvoid initialise_threads(int readq, int fragq, int bwriteq, int fwriteq, int freelst, char *destination_file) {\n\tint i;\n\tsigset_t sigmask, old_mask;\n\tint total_mem = readq;\n\tint reader_size;\n\tint fragment_size;\n\tint fwriter_size;\n\t/*\n\t * bwriter_size is global because it is needed in\n\t * write_file_blocks_dup()\n\t */\n\n\t/*\n\t * Never allow the total size of the queues to be larger than\n\t * physical memory\n\t *\n\t * When adding together the possibly user supplied values, make\n\t * sure they've not been deliberately contrived to overflow an int\n\t */\n\tif (add_overflow(total_mem, fragq))\n\t\tBAD_ERROR(\"Queue sizes rediculously too large\\n\");\n\ttotal_mem += fragq;\n\tif (add_overflow(total_mem, bwriteq))\n\t\tBAD_ERROR(\"Queue sizes rediculously too large\\n\");\n\ttotal_mem += bwriteq;\n\tif (add_overflow(total_mem, fwriteq))\n\t\tBAD_ERROR(\"Queue sizes rediculously too large\\n\");\n\ttotal_mem += fwriteq;\n\n\tif (total_mem > get_physical_memory()) {\n\t\tERROR(\"Total queue sizes larger than physical memory.\\n\");\n\t\tERROR(\"Mksquashfs will exhaust physical memory and thrash.\\n\");\n\t\tBAD_ERROR(\"Queues too large\\n\");\n\t}\n\n\t/*\n\t * convert from queue size in Mbytes to queue size in\n\t * blocks.\n\t *\n\t * This isn't going to overflow an int unless there exists\n\t * systems with more than 8 Petabytes of RAM!\n\t */\n\treader_size = readq << (20 - block_log);\n\tfragment_size = fragq << (20 - block_log);\n\tbwriter_size = bwriteq << (20 - block_log);\n\tfwriter_size = fwriteq << (20 - block_log);\n\n\t/*\n\t * setup signal handlers for the main thread, these cleanup\n\t * deleting the destination file, if appending the\n\t * handlers for SIGTERM and SIGINT will be replaced with handlers\n\t * allowing the user to press ^C twice to restore the existing\n\t * filesystem.\n\t *\n\t * SIGUSR1 is an internal signal, which is used by the sub-threads\n\t * to tell the main thread to terminate, deleting the destination file,\n\t * or if necessary restoring the filesystem on appending\n\t */\n\tsignal(SIGTERM, sighandler);\n\tsignal(SIGINT, sighandler);\n\tsignal(SIGUSR1, sighandler);\n\n\t/* block SIGQUIT and SIGHUP, these are handled by the info thread */\n\tsigemptyset(&sigmask);\n\tsigaddset(&sigmask, SIGQUIT);\n\tsigaddset(&sigmask, SIGHUP);\n\tif (pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == -1)\n\t\tBAD_ERROR(\"Failed to set signal mask in intialise_threads\\n\");\n\n\t/*\n\t * temporarily block these signals, so the created sub-threads\n\t * will ignore them, ensuring the main thread handles them\n\t */\n\tsigemptyset(&sigmask);\n\tsigaddset(&sigmask, SIGINT);\n\tsigaddset(&sigmask, SIGTERM);\n\tsigaddset(&sigmask, SIGUSR1);\n\tif (pthread_sigmask(SIG_BLOCK, &sigmask, &old_mask) == -1)\n\t\tBAD_ERROR(\"Failed to set signal mask in intialise_threads\\n\");\n\n\tif (processors == -1) {\n#ifndef linux\n\t\tint mib[2];\n\t\tsize_t len = sizeof(processors);\n\n\t\tmib[0] = CTL_HW;\n#    ifdef HW_AVAILCPU\n\t\tmib[1] = HW_AVAILCPU;\n#    else\n\t\tmib[1] = HW_NCPU;\n#    endif\n\n\t\tif (sysctl(mib, 2, &processors, &len, NULL, 0) == -1) {\n\t\t\tERROR_START(\"Failed to get number of available \" \"processors.\");\n\t\t\tERROR_EXIT(\"  Defaulting to 1\\n\");\n\t\t\tprocessors = 1;\n\t\t}\n#else\n\t\tprocessors = sysconf(_SC_NPROCESSORS_ONLN);\n#endif\n\t}\n\n\tif (multiply_overflow(processors, 3) || multiply_overflow(processors * 3, sizeof(pthread_t)))\n\t\tBAD_ERROR(\"Processors too large\\n\");\n\n\tdeflator_thread = malloc(processors * 3 * sizeof(pthread_t));\n\tif (deflator_thread == NULL)\n\t\tMEM_ERROR();\n\n\tfrag_deflator_thread = &deflator_thread[processors];\n\tfrag_thread = &frag_deflator_thread[processors];\n\n\tto_reader = queue_init(1);\n\tto_deflate = queue_init(reader_size);\n\tto_process_frag = queue_init(reader_size);\n\tto_writer = queue_init(bwriter_size + fwriter_size);\n\tfrom_writer = queue_init(1);\n\tto_frag = queue_init(fragment_size);\n\tlocked_fragment = queue_init(fragment_size);\n\tto_main = seq_queue_init();\n\treader_buffer = cache_init(block_size, reader_size, 0, 0);\n\tbwriter_buffer = cache_init(block_size, bwriter_size, 1, freelst);\n\tfwriter_buffer = cache_init(block_size, fwriter_size, 1, freelst);\n\tfragment_buffer = cache_init(block_size, fragment_size, 1, 0);\n\treserve_cache = cache_init(block_size, processors + 1, 1, 0);\n\tpthread_create(&reader_thread, NULL, reader, NULL);\n\tpthread_create(&writer_thread, NULL, writer, NULL);\n\tinit_progress_bar();\n\tinit_info();\n\n\tfor (i = 0; i < processors; i++) {\n\t\tif (pthread_create(&deflator_thread[i], NULL, deflator, NULL))\n\t\t\tBAD_ERROR(\"Failed to create thread\\n\");\n\t\tif (pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0)\n\t\t\tBAD_ERROR(\"Failed to create thread\\n\");\n\t\tif (pthread_create(&frag_thread[i], NULL, frag_thrd, (void *)destination_file) != 0)\n\t\t\tBAD_ERROR(\"Failed to create thread\\n\");\n\t}\n\n\tmain_thread = pthread_self();\n\n\tprintf(\"Parallel mksquashfs: Using %d processor%s\\n\", processors, processors == 1 ? \"\" : \"s\");\n\n\t/* Restore the signal mask for the main thread */\n\tif (pthread_sigmask(SIG_SETMASK, &old_mask, NULL) == -1)\n\t\tBAD_ERROR(\"Failed to set signal mask in intialise_threads\\n\");\n}\n\nlong long write_inode_lookup_table() {\n\tint i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count);\n\tvoid *it;\n\n\tif (inode_count == sinode_count)\n\t\tgoto skip_inode_hash_table;\n\n\tit = realloc(inode_lookup_table, lookup_bytes);\n\tif (it == NULL)\n\t\tMEM_ERROR();\n\tinode_lookup_table = it;\n\n\tfor (i = 0; i < INODE_HASH_SIZE; i++) {\n\t\tstruct inode_info *inode;\n\n\t\tfor (inode = inode_info[i]; inode; inode = inode->next) {\n\n\t\t\tinode_number = get_inode_no(inode);\n\n\t\t\tSQUASHFS_SWAP_LONG_LONGS(&inode->inode, &inode_lookup_table[inode_number - 1], 1);\n\n\t\t}\n\t}\n\n skip_inode_hash_table:\n\treturn generic_write_table(lookup_bytes, inode_lookup_table, 0, NULL, noI);\n}\n\nchar *get_component(char *target, char **targname) {\n\tchar *start;\n\n\twhile (*target == '/')\n\t\ttarget++;\n\n\tstart = target;\n\twhile (*target != '/' && *target != '\\0')\n\t\ttarget++;\n\n\t*targname = strndup(start, target - start);\n\n\twhile (*target == '/')\n\t\ttarget++;\n\n\treturn target;\n}\n\nvoid free_path(struct pathname *paths) {\n\tint i;\n\n\tfor (i = 0; i < paths->names; i++) {\n\t\tif (paths->name[i].paths)\n\t\t\tfree_path(paths->name[i].paths);\n\t\tfree(paths->name[i].name);\n\t\tif (paths->name[i].preg) {\n\t\t\tregfree(paths->name[i].preg);\n\t\t\tfree(paths->name[i].preg);\n\t\t}\n\t}\n\n\tfree(paths);\n}\n\nstruct pathname *add_path(struct pathname *paths, char *target, char *alltarget) {\n\tchar *targname;\n\tint i, error;\n\n\ttarget = get_component(target, &targname);\n\n\tif (paths == NULL) {\n\t\tpaths = malloc(sizeof(struct pathname));\n\t\tif (paths == NULL)\n\t\t\tMEM_ERROR();\n\n\t\tpaths->names = 0;\n\t\tpaths->name = NULL;\n\t}\n\n\tfor (i = 0; i < paths->names; i++)\n\t\tif (strcmp(paths->name[i].name, targname) == 0)\n\t\t\tbreak;\n\n\tif (i == paths->names) {\n\t\t/* allocate new name entry */\n\t\tpaths->names++;\n\t\tpaths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry));\n\t\tif (paths->name == NULL)\n\t\t\tMEM_ERROR();\n\t\tpaths->name[i].name = targname;\n\t\tpaths->name[i].paths = NULL;\n\t\tif (use_regex) {\n\t\t\tpaths->name[i].preg = malloc(sizeof(regex_t));\n\t\t\tif (paths->name[i].preg == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t\terror = regcomp(paths->name[i].preg, targname, REG_EXTENDED | REG_NOSUB);\n\t\t\tif (error) {\n\t\t\t\tchar str[1024];\t/* overflow safe */\n\n\t\t\t\tregerror(error, paths->name[i].preg, str, 1024);\n\t\t\t\tBAD_ERROR(\"invalid regex %s in export %s, \" \"because %s\\n\", targname, alltarget, str);\n\t\t\t}\n\t\t} else\n\t\t\tpaths->name[i].preg = NULL;\n\n\t\tif (target[0] == '\\0')\n\t\t\t/* at leaf pathname component */\n\t\t\tpaths->name[i].paths = NULL;\n\t\telse\n\t\t\t/* recurse adding child components */\n\t\t\tpaths->name[i].paths = add_path(NULL, target, alltarget);\n\t} else {\n\t\t/* existing matching entry */\n\t\tfree(targname);\n\n\t\tif (paths->name[i].paths == NULL) {\n\t\t\t/* No sub-directory which means this is the leaf\n\t\t\t * component of a pre-existing exclude which subsumes\n\t\t\t * the exclude currently being added, in which case stop\n\t\t\t * adding components */\n\t\t} else if (target[0] == '\\0') {\n\t\t\t/* at leaf pathname component and child components exist\n\t\t\t * from more specific excludes, delete as they're\n\t\t\t * subsumed by this exclude */\n\t\t\tfree_path(paths->name[i].paths);\n\t\t\tpaths->name[i].paths = NULL;\n\t\t} else\n\t\t\t/* recurse adding child components */\n\t\t\tadd_path(paths->name[i].paths, target, alltarget);\n\t}\n\n\treturn paths;\n}\n\nvoid add_exclude(char *target) {\n\n\tif (target[0] == '/' || strncmp(target, \"./\", 2) == 0 || strncmp(target, \"../\", 3) == 0)\n\t\tBAD_ERROR(\"/, ./ and ../ prefixed excludes not supported with \" \"-wildcards or -regex options\\n\");\n\telse if (strncmp(target, \"... \", 4) == 0)\n\t\tstickypath = add_path(stickypath, target + 4, target + 4);\n\telse\n\t\tpath = add_path(path, target, target);\n}\n\nvoid display_path(int depth, struct pathname *paths) {\n\tint i, n;\n\n\tif (paths == NULL)\n\t\treturn;\n\n\tfor (i = 0; i < paths->names; i++) {\n\t\tfor (n = 0; n < depth; n++)\n\t\t\tprintf(\"\\t\");\n\t\tprintf(\"%d: %s\\n\", depth, paths->name[i].name);\n\t\tdisplay_path(depth + 1, paths->name[i].paths);\n\t}\n}\n\nvoid display_path2(struct pathname *paths, char *string) {\n\tint i;\n\tchar *path;\n\n\tif (paths == NULL) {\n\t\tprintf(\"%s\\n\", string);\n\t\treturn;\n\t}\n\n\tfor (i = 0; i < paths->names; i++) {\n\t\tint res = asprintf(&path, \"%s/%s\", string, paths->name[i].name);\n\t\tif (res == -1)\n\t\t\tBAD_ERROR(\"asprintf failed in display_path2\\n\");\n\t\tdisplay_path2(paths->name[i].paths, path);\n\t\tfree(path);\n\t}\n}\n\nstruct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) {\n\tint count = paths == NULL ? 0 : paths->count;\n\n\tif (count % PATHS_ALLOC_SIZE == 0) {\n\t\tpaths = realloc(paths, sizeof(struct pathnames) + (count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *));\n\t\tif (paths == NULL)\n\t\t\tMEM_ERROR();\n\t}\n\n\tpaths->path[count] = path;\n\tpaths->count = count + 1;\n\treturn paths;\n}\n\nint excluded_match(char *name, struct pathname *path, struct pathnames **new) {\n\tint i;\n\n\tfor (i = 0; i < path->names; i++) {\n\t\tint match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0,\n\t\t\t\t\t\t\t\t\t\tNULL, 0) == 0 : fnmatch(path->name[i].name, name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tFNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) == 0;\n\n\t\tif (match) {\n\t\t\tif (path->name[i].paths == NULL || new == NULL)\n\t\t\t\t/* match on a leaf component, any subdirectories\n\t\t\t\t * in the filesystem should be excluded */\n\t\t\t\treturn TRUE;\n\t\t\telse\n\t\t\t\t/* match on a non-leaf component, add any\n\t\t\t\t * subdirectories to the new set of\n\t\t\t\t * subdirectories to scan for this name */\n\t\t\t\t*new = add_subdir(*new, path->name[i].paths);\n\t\t}\n\t}\n\n\treturn FALSE;\n}\n\nint excluded(char *name, struct pathnames *paths, struct pathnames **new) {\n\tint n;\n\n\tif (stickypath && excluded_match(name, stickypath, NULL))\n\t\treturn TRUE;\n\n\tfor (n = 0; paths && n < paths->count; n++) {\n\t\tint res = excluded_match(name, paths->path[n], new);\n\t\tif (res) {\n\t\t\tfree(*new);\n\t\t\t*new = NULL;\n\t\t\treturn TRUE;\n\t\t}\n\t}\n\n\t/*\n\t * Either:\n\t * -  no matching names found, return empty new search set, or\n\t * -  one or more matches with sub-directories found (no leaf matches),\n\t *    in which case return new search set.\n\t *\n\t * In either case return FALSE as we don't want to exclude this entry\n\t */\n\treturn FALSE;\n}\n\nvoid process_exclude_file(char *argv) {\n\tFILE *fd;\n\tchar buffer[MAX_LINE + 1];\t/* overflow safe */\n\tchar *filename;\n\n\tfd = fopen(argv, \"r\");\n\tif (fd == NULL)\n\t\tBAD_ERROR(\"Failed to open exclude file \\\"%s\\\" because %s\\n\", argv, strerror(errno));\n\n\twhile (fgets(filename = buffer, MAX_LINE + 1, fd) != NULL) {\n\t\tint len = strlen(filename);\n\n\t\tif (len == MAX_LINE && filename[len - 1] != '\\n')\n\t\t\t/* line too large */\n\t\t\tBAD_ERROR(\"Line too long when reading \" \"exclude file \\\"%s\\\", larger than %d \" \"bytes\\n\", argv, MAX_LINE);\n\n\t\t/*\n\t\t * Remove '\\n' terminator if it exists (the last line\n\t\t * in the file may not be '\\n' terminated)\n\t\t */\n\t\tif (len && filename[len - 1] == '\\n')\n\t\t\tfilename[len - 1] = '\\0';\n\n\t\t/* Skip any leading whitespace */\n\t\twhile (isspace(*filename))\n\t\t\tfilename++;\n\n\t\t/* if comment line, skip */\n\t\tif (*filename == '#')\n\t\t\tcontinue;\n\n\t\t/*\n\t\t * check for initial backslash, to accommodate\n\t\t * filenames with leading space or leading # character\n\t\t */\n\t\tif (*filename == '\\\\')\n\t\t\tfilename++;\n\n\t\t/* if line is now empty after skipping characters, skip it */\n\t\tif (*filename == '\\0')\n\t\t\tcontinue;\n\n\t\tif (old_exclude)\n\t\t\told_add_exclude(filename);\n\t\telse\n\t\t\tadd_exclude(filename);\n\t}\n\n\tif (ferror(fd))\n\t\tBAD_ERROR(\"Reading exclude file \\\"%s\\\" failed because %s\\n\", argv, strerror(errno));\n\n\tfclose(fd);\n}\n\n#define RECOVER_ID \"Squashfs recovery file v1.0\\n\"\n#define RECOVER_ID_SIZE 28\n\nvoid write_recovery_data(struct squashfs_super_block *sBlk) {\n\tint res, recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start;\n\tpid_t pid = getpid();\n\tchar *metadata;\n\tchar header[] = RECOVER_ID;\n\n\tif (recover == FALSE) {\n\t\tprintf(\"No recovery data option specified.\\n\");\n\t\tprintf(\"Skipping saving recovery file.\\n\\n\");\n\t\treturn;\n\t}\n\n\tmetadata = malloc(bytes);\n\tif (metadata == NULL)\n\t\tMEM_ERROR();\n\n\tres = read_fs_bytes(fd, sBlk->inode_table_start, bytes, metadata);\n\tif (res == 0) {\n\t\tERROR(\"Failed to read append filesystem metadata\\n\");\n\t\tBAD_ERROR(\"Filesystem corrupted?\\n\");\n\t}\n\n\tres = asprintf(&recovery_file, \"squashfs_recovery_%s_%d\", getbase(destination_file), pid);\n\tif (res == -1)\n\t\tMEM_ERROR();\n\n\trecoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);\n\tif (recoverfd == -1)\n\t\tBAD_ERROR(\"Failed to create recovery file, because %s.  \" \"Aborting\\n\", strerror(errno));\n\n\tif (write_bytes(recoverfd, header, RECOVER_ID_SIZE) == -1)\n\t\tBAD_ERROR(\"Failed to write recovery file, because %s\\n\", strerror(errno));\n\n\tif (write_bytes(recoverfd, sBlk, sizeof(struct squashfs_super_block)) == -1)\n\t\tBAD_ERROR(\"Failed to write recovery file, because %s\\n\", strerror(errno));\n\n\tif (write_bytes(recoverfd, metadata, bytes) == -1)\n\t\tBAD_ERROR(\"Failed to write recovery file, because %s\\n\", strerror(errno));\n\n\tclose(recoverfd);\n\tfree(metadata);\n\n\tprintf(\"Recovery file \\\"%s\\\" written\\n\", recovery_file);\n\tprintf(\"If Mksquashfs aborts abnormally (i.e. power failure), run\\n\");\n\tprintf(\"mksquashfs dummy %s -recover %s\\n\", destination_file, recovery_file);\n\tprintf(\"to restore filesystem\\n\\n\");\n}\n\nvoid read_recovery_data(char *recovery_file, char *destination_file) {\n\tint fd, recoverfd, bytes;\n\tstruct squashfs_super_block orig_sBlk, sBlk;\n\tchar *metadata;\n\tint res;\n\tstruct stat buf;\n\tchar header[] = RECOVER_ID;\n\tchar header2[RECOVER_ID_SIZE];\n\n\trecoverfd = open(recovery_file, O_RDONLY);\n\tif (recoverfd == -1)\n\t\tBAD_ERROR(\"Failed to open recovery file because %s\\n\", strerror(errno));\n\n\tif (stat(destination_file, &buf) == -1)\n\t\tBAD_ERROR(\"Failed to stat destination file, because %s\\n\", strerror(errno));\n\n\tfd = open(destination_file, O_RDWR);\n\tif (fd == -1)\n\t\tBAD_ERROR(\"Failed to open destination file because %s\\n\", strerror(errno));\n\n\tres = read_bytes(recoverfd, header2, RECOVER_ID_SIZE);\n\tif (res == -1)\n\t\tBAD_ERROR(\"Failed to read recovery file, because %s\\n\", strerror(errno));\n\tif (res < RECOVER_ID_SIZE)\n\t\tBAD_ERROR(\"Recovery file appears to be truncated\\n\");\n\tif (strncmp(header, header2, RECOVER_ID_SIZE) != 0)\n\t\tBAD_ERROR(\"Not a recovery file\\n\");\n\n\tres = read_bytes(recoverfd, &sBlk, sizeof(struct squashfs_super_block));\n\tif (res == -1)\n\t\tBAD_ERROR(\"Failed to read recovery file, because %s\\n\", strerror(errno));\n\tif (res < sizeof(struct squashfs_super_block))\n\t\tBAD_ERROR(\"Recovery file appears to be truncated\\n\");\n\n\tres = read_fs_bytes(fd, 0, sizeof(struct squashfs_super_block), &orig_sBlk);\n\tif (res == 0) {\n\t\tERROR(\"Failed to read superblock from output filesystem\\n\");\n\t\tBAD_ERROR(\"Output filesystem is empty!\\n\");\n\t}\n\n\tif (memcmp(((char *)&sBlk) + 4, ((char *)&orig_sBlk) + 4, sizeof(struct squashfs_super_block) - 4) != 0)\n\t\tBAD_ERROR(\"Recovery file and destination file do not seem to \" \"match\\n\");\n\n\tbytes = sBlk.bytes_used - sBlk.inode_table_start;\n\n\tmetadata = malloc(bytes);\n\tif (metadata == NULL)\n\t\tMEM_ERROR();\n\n\tres = read_bytes(recoverfd, metadata, bytes);\n\tif (res == -1)\n\t\tBAD_ERROR(\"Failed to read recovery file, because %s\\n\", strerror(errno));\n\tif (res < bytes)\n\t\tBAD_ERROR(\"Recovery file appears to be truncated\\n\");\n\n\twrite_destination(fd, 0, sizeof(struct squashfs_super_block), &sBlk);\n\n\twrite_destination(fd, sBlk.inode_table_start, bytes, metadata);\n\n\tclose(recoverfd);\n\tclose(fd);\n\n\tprintf(\"Successfully wrote recovery file \\\"%s\\\".  Exiting\\n\", recovery_file);\n\n\texit(0);\n}\n\nvoid write_filesystem_tables(struct squashfs_super_block *sBlk, int nopad) {\n\tint i;\n\n\tsBlk->fragments = fragments;\n\tsBlk->no_ids = id_count;\n\tsBlk->inode_table_start = write_inodes();\n\tsBlk->directory_table_start = write_directories();\n\tsBlk->fragment_table_start = write_fragment_table();\n\tsBlk->lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK;\n\tsBlk->id_table_start = write_id_table();\n\tsBlk->xattr_id_table_start = write_xattrs();\n\n\tTRACE(\"sBlk->inode_table_start 0x%llx\\n\", sBlk->inode_table_start);\n\tTRACE(\"sBlk->directory_table_start 0x%llx\\n\", sBlk->directory_table_start);\n\tTRACE(\"sBlk->fragment_table_start 0x%llx\\n\", sBlk->fragment_table_start);\n\tif (exportable)\n\t\tTRACE(\"sBlk->lookup_table_start 0x%llx\\n\", sBlk->lookup_table_start);\n\n\tsBlk->bytes_used = bytes;\n\n\tsBlk->compression = comp->id;\n\n\tSQUASHFS_INSWAP_SUPER_BLOCK(sBlk);\n\twrite_destination(fd, SQUASHFS_START, sizeof(*sBlk), sBlk);\n\n\tif (!nopad && (i = bytes & (4096 - 1))) {\n\t\tchar temp[4096] = { 0 };\n\t\twrite_destination(fd, bytes, 4096 - i, temp);\n\t}\n\n\tclose(fd);\n\n\tif (recovery_file)\n\t\tunlink(recovery_file);\n\n\ttotal_bytes += total_inode_bytes + total_directory_bytes + sizeof(struct squashfs_super_block) + total_xattr_bytes;\n\n\tprintf(\"\\n%sSquashfs %d.%d filesystem, %s compressed, data block size\" \" %d\\n\", exportable ? \"Exportable \" : \"\", SQUASHFS_MAJOR, SQUASHFS_MINOR, comp->name, block_size);\n\tprintf(\"\\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\");\n\tprintf(\"\\tduplicates are %sremoved\\n\", duplicate_checking ? \"\" : \"not \");\n\tprintf(\"Filesystem size %.2f Kbytes (%.2f Mbytes)\\n\", bytes / 1024.0, bytes / (1024.0 * 1024.0));\n\tprintf(\"\\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\\n\", ((float)bytes / total_bytes) * 100.0, total_bytes / 1024.0);\n\tprintf(\"Inode table size %d bytes (%.2f Kbytes)\\n\", inode_bytes, inode_bytes / 1024.0);\n\tprintf(\"\\t%.2f%% of uncompressed inode table size (%d bytes)\\n\", ((float)inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes);\n\tprintf(\"Directory table size %d bytes (%.2f Kbytes)\\n\", directory_bytes, directory_bytes / 1024.0);\n\tprintf(\"\\t%.2f%% of uncompressed directory table size (%d bytes)\\n\", ((float)directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes);\n\tif (total_xattr_bytes) {\n\t\tprintf(\"Xattr table size %d bytes (%.2f Kbytes)\\n\", xattr_bytes, xattr_bytes / 1024.0);\n\t\tprintf(\"\\t%.2f%% of uncompressed xattr table size (%d bytes)\\n\", ((float)xattr_bytes / total_xattr_bytes) * 100.0, total_xattr_bytes);\n\t}\n\tif (duplicate_checking)\n\t\tprintf(\"Number of duplicate files found %d\\n\", file_count - dup_files);\n\telse\n\t\tprintf(\"No duplicate files removed\\n\");\n\tprintf(\"Number of inodes %d\\n\", inode_count);\n\tprintf(\"Number of files %d\\n\", file_count);\n\tif (!no_fragments)\n\t\tprintf(\"Number of fragments %d\\n\", fragments);\n\tprintf(\"Number of symbolic links  %d\\n\", sym_count);\n\tprintf(\"Number of device nodes %d\\n\", dev_count);\n\tprintf(\"Number of fifo nodes %d\\n\", fifo_count);\n\tprintf(\"Number of socket nodes %d\\n\", sock_count);\n\tprintf(\"Number of directories %d\\n\", dir_count);\n\tprintf(\"Number of ids (unique uids + gids) %d\\n\", id_count);\n\tprintf(\"Number of uids %d\\n\", uid_count);\n\n\tfor (i = 0; i < id_count; i++) {\n\t\tif (id_table[i]->flags & ISA_UID) {\n\t\t\tstruct passwd *user = getpwuid(id_table[i]->id);\n\t\t\tprintf(\"\\t%s (%d)\\n\", user == NULL ? \"unknown\" : user->pw_name, id_table[i]->id);\n\t\t}\n\t}\n\n\tprintf(\"Number of gids %d\\n\", guid_count);\n\n\tfor (i = 0; i < id_count; i++) {\n\t\tif (id_table[i]->flags & ISA_GID) {\n\t\t\tstruct group *group = getgrgid(id_table[i]->id);\n\t\t\tprintf(\"\\t%s (%d)\\n\", group == NULL ? \"unknown\" : group->gr_name, id_table[i]->id);\n\t\t}\n\t}\n}\n\nint parse_numberll(char *start, long long *res, int size) {\n\tchar *end;\n\tlong long number;\n\n\terrno = 0;\t\t\t\t\t/* To distinguish success/failure after call */\n\n\tnumber = strtoll(start, &end, 10);\n\n\t/*\n\t * check for strtoll underflow or overflow in conversion, and other\n\t * errors.\n\t */\n\tif ((errno == ERANGE && (number == LLONG_MIN || number == LLONG_MAX)) || (errno != 0 && number == 0))\n\t\treturn 0;\n\n\t/* reject negative numbers as invalid */\n\tif (number < 0)\n\t\treturn 0;\n\n\tif (size) {\n\t\t/*\n\t\t * Check for multiplier and trailing junk.\n\t\t * But first check that a number exists before the\n\t\t * multiplier\n\t\t */\n\t\tif (end == start)\n\t\t\treturn 0;\n\n\t\tswitch (end[0]) {\n\t\tcase 'g':\n\t\tcase 'G':\n\t\t\tif (multiply_overflowll(number, 1073741824))\n\t\t\t\treturn 0;\n\t\t\tnumber *= 1073741824;\n\n\t\t\tif (end[1] != '\\0')\n\t\t\t\t/* trailing junk after multiplier, but\n\t\t\t\t * allow it to be \"bytes\" */\n\t\t\t\tif (strcmp(end + 1, \"bytes\"))\n\t\t\t\t\treturn 0;\n\n\t\t\tbreak;\n\t\tcase 'm':\n\t\tcase 'M':\n\t\t\tif (multiply_overflowll(number, 1048576))\n\t\t\t\treturn 0;\n\t\t\tnumber *= 1048576;\n\n\t\t\tif (end[1] != '\\0')\n\t\t\t\t/* trailing junk after multiplier, but\n\t\t\t\t * allow it to be \"bytes\" */\n\t\t\t\tif (strcmp(end + 1, \"bytes\"))\n\t\t\t\t\treturn 0;\n\n\t\t\tbreak;\n\t\tcase 'k':\n\t\tcase 'K':\n\t\t\tif (multiply_overflowll(number, 1024))\n\t\t\t\treturn 0;\n\t\t\tnumber *= 1024;\n\n\t\t\tif (end[1] != '\\0')\n\t\t\t\t/* trailing junk after multiplier, but\n\t\t\t\t * allow it to be \"bytes\" */\n\t\t\t\tif (strcmp(end + 1, \"bytes\"))\n\t\t\t\t\treturn 0;\n\n\t\t\tbreak;\n\t\tcase '\\0':\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t/* trailing junk after number */\n\t\t\treturn 0;\n\t\t}\n\t} else if (end[0] != '\\0')\n\t\t/* trailing junk after number */\n\t\treturn 0;\n\n\t*res = number;\n\treturn 1;\n}\n\nint parse_number(char *start, int *res, int size) {\n\tlong long number;\n\n\tif (!parse_numberll(start, &number, size))\n\t\treturn 0;\n\n\t/* check if long result will overflow signed int */\n\tif (number > INT_MAX)\n\t\treturn 0;\n\n\t*res = (int)number;\n\treturn 1;\n}\n\nint parse_num(char *arg, int *res) {\n\treturn parse_number(arg, res, 0);\n}\n\nint get_physical_memory() {\n\t/* Long longs are used here because with PAE, a 32-bit\n\t   machine can have more than 4GB of physical memory */\n\n\tlong long num_pages = sysconf(_SC_PHYS_PAGES);\n\tlong long page_size = sysconf(_SC_PAGESIZE);\n\tint phys_mem = num_pages * page_size >> 20;\n\n\tif (phys_mem < SQUASHFS_LOWMEM)\n\t\tBAD_ERROR(\"Mksquashfs requires more physical memory than is \" \"available!\\n\");\n\n\treturn phys_mem;\n}\n\nvoid calculate_queue_sizes(int mem, int *readq, int *fragq, int *bwriteq, int *fwriteq) {\n\t*readq = mem / SQUASHFS_READQ_MEM;\n\t*bwriteq = mem / SQUASHFS_BWRITEQ_MEM;\n\t*fwriteq = mem / SQUASHFS_FWRITEQ_MEM;\n\t*fragq = mem - *readq - *bwriteq - *fwriteq;\n}\n\n#define VERSION() \\\n\tprintf(\"mksquashfs version 4.3 (2014/05/12)\\n\");\\\n\tprintf(\"copyright (C) 2014 Phillip Lougher \"\\\n\t\t\"<phillip@squashfs.org.uk>\\n\\n\"); \\\n\tprintf(\"This program is free software; you can redistribute it and/or\"\\\n\t\t\"\\n\");\\\n\tprintf(\"modify it under the terms of the GNU General Public License\"\\\n\t\t\"\\n\");\\\n\tprintf(\"as published by the Free Software Foundation; either version \"\\\n\t\t\"2,\\n\");\\\n\tprintf(\"or (at your option) any later version.\\n\\n\");\\\n\tprintf(\"This program is distributed in the hope that it will be \"\\\n\t\t\"useful,\\n\");\\\n\tprintf(\"but WITHOUT ANY WARRANTY; without even the implied warranty \"\\\n\t\t\"of\\n\");\\\n\tprintf(\"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\"\\\n\t\t\"\\n\");\\\n\tprintf(\"GNU General Public License for more details.\\n\");\nint main(int argc, char *argv[]) {\n\tstruct stat buf, source_buf;\n\tint res, i;\n\tchar *b, *root_name = NULL;\n\tint keep_as_directory = FALSE;\n\tsquashfs_inode inode;\n\tint readq;\n\tint fragq;\n\tint bwriteq;\n\tint fwriteq;\n\tint total_mem = get_physical_memory() / SQUASHFS_TAKE;\n\tint progress = TRUE;\n\tint force_progress = FALSE;\n\tstruct file_buffer **fragment = NULL;\n\n\tif (argc > 1 && strcmp(argv[1], \"-version\") == 0) {\n\t\tVERSION();\n\t\texit(0);\n\t}\n\n\tblock_log = slog(block_size);\n\tcalculate_queue_sizes(total_mem, &readq, &fragq, &bwriteq, &fwriteq);\n\n\tfor (i = 1; i < argc && argv[i][0] != '-'; i++) ;\n\tif (i < 3)\n\t\tgoto printOptions;\n\tsource_path = argv + 1;\n\tsource = i - 2;\n\n\t/*\n\t * Scan the command line for -comp xxx option, this is to ensure\n\t * any -X compressor specific options are passed to the\n\t * correct compressor\n\t */\n\tfor (; i < argc; i++) {\n\t\tstruct compressor *prev_comp = comp;\n\n\t\tif (strcmp(argv[i], \"-comp\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -comp missing compression type\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tcomp = lookup_compressor(argv[i]);\n\t\t\tif (!comp->supported) {\n\t\t\t\tERROR(\"%s: Compressor \\\"%s\\\" is not supported!\" \"\\n\", argv[0], argv[i]);\n\t\t\t\tERROR(\"%s: Compressors available:\\n\", argv[0]);\n\t\t\t\tdisplay_compressors(\"\", COMP_DEFAULT);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif (prev_comp != NULL && prev_comp != comp) {\n\t\t\t\tERROR(\"%s: -comp multiple conflicting -comp\" \" options specified on command line\" \", previously %s, now %s\\n\", argv[0], prev_comp->name, comp->name);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tcompressor_opt_parsed = 1;\n\n\t\t} else if (strcmp(argv[i], \"-e\") == 0)\n\t\t\tbreak;\n\t\telse if (strcmp(argv[i], \"-root-becomes\") == 0 || strcmp(argv[i], \"-ef\") == 0 || strcmp(argv[i], \"-pf\") == 0 || strcmp(argv[i], \"-af\") == 0 || strcmp(argv[i], \"-comp\") == 0)\n\t\t\ti++;\n\t}\n\n\t/*\n\t * if no -comp option specified lookup default compressor.  Note the\n\t * Makefile ensures the default compressor has been built, and so we\n\t * don't need to to check for failure here\n\t */\n\tif (comp == NULL)\n\t\tcomp = lookup_compressor(COMP_DEFAULT);\n\n\tfor (i = source + 2; i < argc; i++) {\n\t\tif (strcmp(argv[i], \"-action\") == 0 || strcmp(argv[i], \"-a\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: %s missing action\\n\", argv[0], argv[i - 1]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tres = parse_action(argv[i]);\n\t\t\tif (res == 0)\n\t\t\t\texit(1);\n\n\t\t} else if (strcmp(argv[i], \"-af\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -af missing filename\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif (read_action_file(argv[i]) == FALSE)\n\t\t\t\texit(1);\n\n\t\t} else if (strcmp(argv[i], \"-comp\") == 0)\n\t\t\t/* parsed previously */\n\t\t\ti++;\n\n\t\telse if (strncmp(argv[i], \"-X\", 2) == 0) {\n\t\t\tint args;\n\n\t\t\tif (strcmp(argv[i] + 2, \"help\") == 0)\n\t\t\t\tgoto print_compressor_options;\n\n\t\t\targs = compressor_options(comp, argv + i, argc - i);\n\t\t\tif (args < 0) {\n\t\t\t\tif (args == -1) {\n\t\t\t\t\tERROR(\"%s: Unrecognised compressor\" \" option %s\\n\", argv[0], argv[i]);\n\t\t\t\t\tif (!compressor_opt_parsed)\n\t\t\t\t\t\tERROR(\"%s: Did you forget to\" \" specify -comp?\\n\", argv[0]);\n print_compressor_options:\n\t\t\t\t\tERROR(\"%s: selected compressor \\\"%s\\\"\" \".  Options supported: %s\\n\", argv[0], comp->name, comp->usage ? \"\" : \"none\");\n\t\t\t\t\tif (comp->usage)\n\t\t\t\t\t\tcomp->usage();\n\t\t\t\t}\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\ti += args;\n\n\t\t} else if (strcmp(argv[i], \"-pf\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -pf missing filename\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif (read_pseudo_file(argv[i]) == FALSE)\n\t\t\t\texit(1);\n\t\t} else if (strcmp(argv[i], \"-p\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -p missing pseudo file definition\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif (read_pseudo_def(argv[i]) == FALSE)\n\t\t\t\texit(1);\n\t\t} else if (strcmp(argv[i], \"-recover\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -recover missing recovery file\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tread_recovery_data(argv[i], argv[source + 1]);\n\t\t} else if (strcmp(argv[i], \"-no-recovery\") == 0)\n\t\t\trecover = FALSE;\n\t\telse if (strcmp(argv[i], \"-wildcards\") == 0) {\n\t\t\told_exclude = FALSE;\n\t\t\tuse_regex = FALSE;\n\t\t} else if (strcmp(argv[i], \"-regex\") == 0) {\n\t\t\told_exclude = FALSE;\n\t\t\tuse_regex = TRUE;\n\t\t} else if (strcmp(argv[i], \"-no-sparse\") == 0)\n\t\t\tsparse_files = FALSE;\n\t\telse if (strcmp(argv[i], \"-no-progress\") == 0)\n\t\t\tprogress = FALSE;\n\t\telse if (strcmp(argv[i], \"-progress\") == 0)\n\t\t\tforce_progress = TRUE;\n\t\telse if (strcmp(argv[i], \"-no-exports\") == 0)\n\t\t\texportable = FALSE;\n\t\telse if (strcmp(argv[i], \"-processors\") == 0) {\n\t\t\tif ((++i == argc) || !parse_num(argv[i], &processors)) {\n\t\t\t\tERROR(\"%s: -processors missing or invalid \" \"processor number\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif (processors < 1) {\n\t\t\t\tERROR(\"%s: -processors should be 1 or larger\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t} else if (strcmp(argv[i], \"-read-queue\") == 0) {\n\t\t\tif ((++i == argc) || !parse_num(argv[i], &readq)) {\n\t\t\t\tERROR(\"%s: -read-queue missing or invalid \" \"queue size\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif (readq < 1) {\n\t\t\t\tERROR(\"%s: -read-queue should be 1 megabyte or \" \"larger\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t} else if (strcmp(argv[i], \"-write-queue\") == 0) {\n\t\t\tif ((++i == argc) || !parse_num(argv[i], &bwriteq)) {\n\t\t\t\tERROR(\"%s: -write-queue missing or invalid \" \"queue size\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif (bwriteq < 2) {\n\t\t\t\tERROR(\"%s: -write-queue should be 2 megabytes \" \"or larger\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tfwriteq = bwriteq >> 1;\n\t\t\tbwriteq -= fwriteq;\n\t\t} else if (strcmp(argv[i], \"-fragment-queue\") == 0) {\n\t\t\tif ((++i == argc) || !parse_num(argv[i], &fragq)) {\n\t\t\t\tERROR(\"%s: -fragment-queue missing or invalid \" \"queue size\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif (fragq < 1) {\n\t\t\t\tERROR(\"%s: -fragment-queue should be 1 \" \"megabyte or larger\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t} else if (strcmp(argv[i], \"-mem\") == 0) {\n\t\t\tlong long number;\n\n\t\t\tif ((++i == argc) || !parse_numberll(argv[i], &number, 1)) {\n\t\t\t\tERROR(\"%s: -mem missing or invalid mem size\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\t/* convert from bytes to Mbytes */\n\t\t\ttotal_mem = number / 1048576;\n\t\t\tif (total_mem < (SQUASHFS_LOWMEM / SQUASHFS_TAKE)) {\n\t\t\t\tERROR(\"%s: -mem should be %d Mbytes or \" \"larger\\n\", argv[0], SQUASHFS_LOWMEM / SQUASHFS_TAKE);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tcalculate_queue_sizes(total_mem, &readq, &fragq, &bwriteq, &fwriteq);\n\t\t} else if (strcmp(argv[i], \"-b\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -b missing block size\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif (!parse_number(argv[i], &block_size, 1)) {\n\t\t\t\tERROR(\"%s: -b invalid block size\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif ((block_log = slog(block_size)) == 0) {\n\t\t\t\tERROR(\"%s: -b block size not power of two or \" \"not between 4096 and 1Mbyte\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t} else if (strcmp(argv[i], \"-ef\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -ef missing filename\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t} else if (strcmp(argv[i], \"-no-duplicates\") == 0)\n\t\t\tduplicate_checking = FALSE;\n\n\t\telse if (strcmp(argv[i], \"-no-fragments\") == 0)\n\t\t\tno_fragments = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-always-use-fragments\") == 0)\n\t\t\talways_use_fragments = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-sort\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -sort missing filename\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t} else if (strcmp(argv[i], \"-all-root\") == 0 || strcmp(argv[i], \"-root-owned\") == 0)\n\t\t\tglobal_uid = global_gid = 0;\n\n\t\telse if (strcmp(argv[i], \"-force-uid\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -force-uid missing uid or user\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif ((global_uid = strtoll(argv[i], &b, 10)), *b == '\\0') {\n\t\t\t\tif (global_uid < 0 || global_uid > (((long long)1 << 32) - 1)) {\n\t\t\t\t\tERROR(\"%s: -force-uid uid out of range\" \"\\n\", argv[0]);\n\t\t\t\t\texit(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tstruct passwd *uid = getpwnam(argv[i]);\n\t\t\t\tif (uid)\n\t\t\t\t\tglobal_uid = uid->pw_uid;\n\t\t\t\telse {\n\t\t\t\t\tERROR(\"%s: -force-uid invalid uid or \" \"unknown user\\n\", argv[0]);\n\t\t\t\t\texit(1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (strcmp(argv[i], \"-force-gid\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -force-gid missing gid or group\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tif ((global_gid = strtoll(argv[i], &b, 10)), *b == '\\0') {\n\t\t\t\tif (global_gid < 0 || global_gid > (((long long)1 << 32) - 1)) {\n\t\t\t\t\tERROR(\"%s: -force-gid gid out of range\" \"\\n\", argv[0]);\n\t\t\t\t\texit(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tstruct group *gid = getgrnam(argv[i]);\n\t\t\t\tif (gid)\n\t\t\t\t\tglobal_gid = gid->gr_gid;\n\t\t\t\telse {\n\t\t\t\t\tERROR(\"%s: -force-gid invalid gid or \" \"unknown group\\n\", argv[0]);\n\t\t\t\t\texit(1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (strcmp(argv[i], \"-noI\") == 0 || strcmp(argv[i], \"-noInodeCompression\") == 0)\n\t\t\tnoI = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-noD\") == 0 || strcmp(argv[i], \"-noDataCompression\") == 0)\n\t\t\tnoD = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-noF\") == 0 || strcmp(argv[i], \"-noFragmentCompression\") == 0)\n\t\t\tnoF = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-noX\") == 0 || strcmp(argv[i], \"-noXattrCompression\") == 0)\n\t\t\tnoX = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-no-xattrs\") == 0)\n\t\t\tno_xattrs = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-xattrs\") == 0)\n\t\t\tno_xattrs = FALSE;\n\n\t\telse if (strcmp(argv[i], \"-nopad\") == 0)\n\t\t\tnopad = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-info\") == 0)\n\t\t\tsilent = FALSE;\n\n\t\telse if (strcmp(argv[i], \"-e\") == 0)\n\t\t\tbreak;\n\n\t\telse if (strcmp(argv[i], \"-noappend\") == 0)\n\t\t\tdelete = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-keep-as-directory\") == 0)\n\t\t\tkeep_as_directory = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-exit-on-error\") == 0)\n\t\t\texit_on_error = TRUE;\n\n\t\telse if (strcmp(argv[i], \"-root-becomes\") == 0) {\n\t\t\tif (++i == argc) {\n\t\t\t\tERROR(\"%s: -root-becomes: missing name\\n\", argv[0]);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\troot_name = argv[i];\n\t\t} else if (strcmp(argv[i], \"-version\") == 0) {\n\t\t\tVERSION();\n\t\t} else {\n\t\t\tERROR(\"%s: invalid option\\n\\n\", argv[0]);\n printOptions:\n\t\t\tERROR(\"SYNTAX:%s source1 source2 ...  dest [options] \" \"[-e list of exclude\\ndirs/files]\\n\", argv[0]);\n\t\t\tERROR(\"\\nFilesystem build options:\\n\");\n\t\t\tERROR(\"-comp <comp>\\t\\tselect <comp> compression\\n\");\n\t\t\tERROR(\"\\t\\t\\tCompressors available:\\n\");\n\t\t\tdisplay_compressors(\"\\t\\t\\t\", COMP_DEFAULT);\n\t\t\tERROR(\"-b <block_size>\\t\\tset data block to \" \"<block_size>.  Default 128 Kbytes\\n\");\n\t\t\tERROR(\"\\t\\t\\tOptionally a suffix of K or M can be\" \" given to specify\\n\\t\\t\\tKbytes or Mbytes\" \" respectively\\n\");\n\t\t\tERROR(\"-no-exports\\t\\tdon't make the filesystem \" \"exportable via NFS\\n\");\n\t\t\tERROR(\"-no-sparse\\t\\tdon't detect sparse files\\n\");\n\t\t\tERROR(\"-no-xattrs\\t\\tdon't store extended attributes\" NOXOPT_STR \"\\n\");\n\t\t\tERROR(\"-xattrs\\t\\t\\tstore extended attributes\" XOPT_STR \"\\n\");\n\t\t\tERROR(\"-noI\\t\\t\\tdo not compress inode table\\n\");\n\t\t\tERROR(\"-noD\\t\\t\\tdo not compress data blocks\\n\");\n\t\t\tERROR(\"-noF\\t\\t\\tdo not compress fragment blocks\\n\");\n\t\t\tERROR(\"-noX\\t\\t\\tdo not compress extended \" \"attributes\\n\");\n\t\t\tERROR(\"-no-fragments\\t\\tdo not use fragments\\n\");\n\t\t\tERROR(\"-always-use-fragments\\tuse fragment blocks for \" \"files larger than block size\\n\");\n\t\t\tERROR(\"-no-duplicates\\t\\tdo not perform duplicate \" \"checking\\n\");\n\t\t\tERROR(\"-all-root\\t\\tmake all files owned by root\\n\");\n\t\t\tERROR(\"-force-uid uid\\t\\tset all file uids to uid\\n\");\n\t\t\tERROR(\"-force-gid gid\\t\\tset all file gids to gid\\n\");\n\t\t\tERROR(\"-nopad\\t\\t\\tdo not pad filesystem to a multiple \" \"of 4K\\n\");\n\t\t\tERROR(\"-keep-as-directory\\tif one source directory is \" \"specified, create a root\\n\");\n\t\t\tERROR(\"\\t\\t\\tdirectory containing that directory, \" \"rather than the\\n\");\n\t\t\tERROR(\"\\t\\t\\tcontents of the directory\\n\");\n\t\t\tERROR(\"\\nFilesystem filter options:\\n\");\n\t\t\tERROR(\"-p <pseudo-definition>\\tAdd pseudo file \" \"definition\\n\");\n\t\t\tERROR(\"-pf <pseudo-file>\\tAdd list of pseudo file \" \"definitions\\n\");\n\t\t\tERROR(\"-sort <sort_file>\\tsort files according to \" \"priorities in <sort_file>.  One\\n\");\n\t\t\tERROR(\"\\t\\t\\tfile or dir with priority per line.  \" \"Priority -32768 to\\n\");\n\t\t\tERROR(\"\\t\\t\\t32767, default priority 0\\n\");\n\t\t\tERROR(\"-ef <exclude_file>\\tlist of exclude dirs/files.\" \"  One per line\\n\");\n\t\t\tERROR(\"-wildcards\\t\\tAllow extended shell wildcards \" \"(globbing) to be used in\\n\\t\\t\\texclude \" \"dirs/files\\n\");\n\t\t\tERROR(\"-regex\\t\\t\\tAllow POSIX regular expressions to \" \"be used in exclude\\n\\t\\t\\tdirs/files\\n\");\n\t\t\tERROR(\"\\nFilesystem append options:\\n\");\n\t\t\tERROR(\"-noappend\\t\\tdo not append to existing \" \"filesystem\\n\");\n\t\t\tERROR(\"-root-becomes <name>\\twhen appending source \" \"files/directories, make the\\n\");\n\t\t\tERROR(\"\\t\\t\\toriginal root become a subdirectory in \" \"the new root\\n\");\n\t\t\tERROR(\"\\t\\t\\tcalled <name>, rather than adding the new \" \"source items\\n\");\n\t\t\tERROR(\"\\t\\t\\tto the original root\\n\");\n\t\t\tERROR(\"\\nMksquashfs runtime options:\\n\");\n\t\t\tERROR(\"-version\\t\\tprint version, licence and \" \"copyright message\\n\");\n\t\t\tERROR(\"-exit-on-error\\t\\ttreat normally ignored errors \" \"as fatal\\n\");\n\t\t\tERROR(\"-recover <name>\\t\\trecover filesystem data \" \"using recovery file <name>\\n\");\n\t\t\tERROR(\"-no-recovery\\t\\tdon't generate a recovery \" \"file\\n\");\n\t\t\tERROR(\"-info\\t\\t\\tprint files written to filesystem\\n\");\n\t\t\tERROR(\"-no-progress\\t\\tdon't display the progress \" \"bar\\n\");\n\t\t\tERROR(\"-progress\\t\\tdisplay progress bar when using \" \"the -info option\\n\");\n\t\t\tERROR(\"-processors <number>\\tUse <number> processors.\" \"  By default will use number of\\n\");\n\t\t\tERROR(\"\\t\\t\\tprocessors available\\n\");\n\t\t\tERROR(\"-mem <size>\\t\\tUse <size> physical memory.  \" \"Currently set to %dM\\n\", total_mem);\n\t\t\tERROR(\"\\t\\t\\tOptionally a suffix of K, M or G can be\" \" given to specify\\n\\t\\t\\tKbytes, Mbytes or\" \" Gbytes respectively\\n\");\n\t\t\tERROR(\"\\nMiscellaneous options:\\n\");\n\t\t\tERROR(\"-root-owned\\t\\talternative name for -all-root\" \"\\n\");\n\t\t\tERROR(\"-noInodeCompression\\talternative name for -noI\" \"\\n\");\n\t\t\tERROR(\"-noDataCompression\\talternative name for -noD\" \"\\n\");\n\t\t\tERROR(\"-noFragmentCompression\\talternative name for \" \"-noF\\n\");\n\t\t\tERROR(\"-noXattrCompression\\talternative name for \" \"-noX\\n\");\n\t\t\tERROR(\"\\n-Xhelp\\t\\t\\tprint compressor options for\" \" selected compressor\\n\");\n\t\t\tERROR(\"\\nCompressors available and compressor specific \" \"options:\\n\");\n\t\t\tdisplay_compressor_usage(COMP_DEFAULT);\n\t\t\texit(1);\n\t\t}\n\t}\n\n\t/*\n\t * Some compressors may need the options to be checked for validity\n\t * once all the options have been processed\n\t */\n\tres = compressor_options_post(comp, block_size);\n\tif (res)\n\t\tEXIT_MKSQUASHFS();\n\n\t/*\n\t * If the -info option has been selected then disable the\n\t * progress bar unless it has been explicitly enabled with\n\t * the -progress option\n\t */\n\tif (!silent)\n\t\tprogress = force_progress;\n\n#ifdef SQUASHFS_TRACE\n\t/*\n\t * Disable progress bar if full debug tracing is enabled.\n\t * The progress bar in this case just gets in the way of the\n\t * debug trace output\n\t */\n\tprogress = FALSE;\n#endif\n\n\tfor (i = 0; i < source; i++)\n\t\tif (lstat(source_path[i], &source_buf) == -1) {\n\t\t\tfprintf(stderr, \"Cannot stat source directory \\\"%s\\\" \" \"because %s\\n\", source_path[i], strerror(errno));\n\t\t\tEXIT_MKSQUASHFS();\n\t\t}\n\n\tdestination_file = argv[source + 1];\n\tif (stat(argv[source + 1], &buf) == -1) {\n\t\tif (errno == ENOENT) {\t/* Does not exist */\n\t\t\tfd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);\n\t\t\tif (fd == -1) {\n\t\t\t\tperror(\"Could not create destination file\");\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tdelete = TRUE;\n\t\t} else {\n\t\t\tperror(\"Could not stat destination file\");\n\t\t\texit(1);\n\t\t}\n\n\t} else {\n\t\tif (S_ISBLK(buf.st_mode)) {\n\t\t\tif ((fd = open(argv[source + 1], O_RDWR)) == -1) {\n\t\t\t\tperror(\"Could not open block device as \" \"destination\");\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tblock_device = 1;\n\n\t\t} else if (S_ISREG(buf.st_mode)) {\n\t\t\tfd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR);\n\t\t\tif (fd == -1) {\n\t\t\t\tperror(\"Could not open regular file for \" \"writing as destination\");\n\t\t\t\texit(1);\n\t\t\t}\n\t\t} else {\n\t\t\tERROR(\"Destination not block device or regular file\\n\");\n\t\t\texit(1);\n\t\t}\n\n\t}\n\n\t/*\n\t * process the exclude files - must be done afer destination file has\n\t * been possibly created\n\t */\n\tfor (i = source + 2; i < argc; i++)\n\t\tif (strcmp(argv[i], \"-ef\") == 0)\n\t\t\t/*\n\t\t\t * Note presence of filename arg has already\n\t\t\t * been checked\n\t\t\t */\n\t\t\tprocess_exclude_file(argv[++i]);\n\t\telse if (strcmp(argv[i], \"-e\") == 0)\n\t\t\tbreak;\n\t\telse if (strcmp(argv[i], \"-root-becomes\") == 0 || strcmp(argv[i], \"-sort\") == 0 || strcmp(argv[i], \"-pf\") == 0 || strcmp(argv[i], \"-af\") == 0 || strcmp(argv[i], \"-comp\") == 0)\n\t\t\ti++;\n\n\tif (i != argc) {\n\t\tif (++i == argc) {\n\t\t\tERROR(\"%s: -e missing arguments\\n\", argv[0]);\n\t\t\tEXIT_MKSQUASHFS();\n\t\t}\n\t\twhile (i < argc)\n\t\t\tif (old_exclude)\n\t\t\t\told_add_exclude(argv[i++]);\n\t\t\telse\n\t\t\t\tadd_exclude(argv[i++]);\n\t}\n\n\t/* process the sort files - must be done afer the exclude files  */\n\tfor (i = source + 2; i < argc; i++)\n\t\tif (strcmp(argv[i], \"-sort\") == 0) {\n\t\t\tint res = read_sort_file(argv[++i], source,\n\t\t\t\t\t\t\t\t\t source_path);\n\t\t\tif (res == FALSE)\n\t\t\t\tBAD_ERROR(\"Failed to read sort file\\n\");\n\t\t\tsorted++;\n\t\t} else if (strcmp(argv[i], \"-e\") == 0)\n\t\t\tbreak;\n\t\telse if (strcmp(argv[i], \"-root-becomes\") == 0 || strcmp(argv[i], \"-ef\") == 0 || strcmp(argv[i], \"-pf\") == 0 || strcmp(argv[i], \"-af\") == 0 || strcmp(argv[i], \"-comp\") == 0)\n\t\t\ti++;\n\n\tif (!delete) {\n\t\tcomp = read_super(fd, &sBlk, argv[source + 1]);\n\t\tif (comp == NULL) {\n\t\t\tERROR(\"Failed to read existing filesystem - will not \" \"overwrite - ABORTING!\\n\");\n\t\t\tERROR(\"To force Mksquashfs to write to this block \" \"device or file use -noappend\\n\");\n\t\t\tEXIT_MKSQUASHFS();\n\t\t}\n\n\t\tblock_log = slog(block_size = sBlk.block_size);\n\t\tnoI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags);\n\t\tnoD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags);\n\t\tnoF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags);\n\t\tnoX = SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.flags);\n\t\tno_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags);\n\t\talways_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags);\n\t\tduplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags);\n\t\texportable = SQUASHFS_EXPORTABLE(sBlk.flags);\n\t\tno_xattrs = SQUASHFS_NO_XATTRS(sBlk.flags);\n\t\tcomp_opts = SQUASHFS_COMP_OPTS(sBlk.flags);\n\t}\n\n\tinitialise_threads(readq, fragq, bwriteq, fwriteq, delete, destination_file);\n\n\tres = compressor_init(comp, &stream, SQUASHFS_METADATA_SIZE, 0);\n\tif (res)\n\t\tBAD_ERROR(\"compressor_init failed\\n\");\n\n\tif (delete) {\n\t\tint size;\n\t\tvoid *comp_data = compressor_dump_options(comp, block_size,\n\t\t\t\t\t\t\t\t\t\t\t\t  &size);\n\n\t\tprintf(\"Creating %d.%d filesystem on %s, block size %d.\\n\", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size);\n\n\t\t/*\n\t\t * store any compressor specific options after the superblock,\n\t\t * and set the COMP_OPT flag to show that the filesystem has\n\t\t * compressor specfic options\n\t\t */\n\t\tif (comp_data) {\n\t\t\tunsigned short c_byte = size | SQUASHFS_COMPRESSED_BIT;\n\n\t\t\tSQUASHFS_INSWAP_SHORTS(&c_byte, 1);\n\t\t\twrite_destination(fd, sizeof(struct squashfs_super_block), sizeof(c_byte), &c_byte);\n\t\t\twrite_destination(fd, sizeof(struct squashfs_super_block) + sizeof(c_byte), size, comp_data);\n\t\t\tbytes = sizeof(struct squashfs_super_block) + sizeof(c_byte)\n\t\t\t\t+ size;\n\t\t\tcomp_opts = TRUE;\n\t\t} else\n\t\t\tbytes = sizeof(struct squashfs_super_block);\n\t} else {\n\t\tunsigned 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;\n\t\tunsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode);\n\n\t\tif ((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) {\n\t\t\tERROR(\"Failed to read existing filesystem - will not \" \"overwrite - ABORTING!\\n\");\n\t\t\tERROR(\"To force Mksquashfs to write to this block \" \"device or file use -noappend\\n\");\n\t\t\tEXIT_MKSQUASHFS();\n\t\t}\n\t\tif ((append_fragments = fragments = sBlk.fragments)) {\n\t\t\tfragment_table = realloc((char *)fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1))\n\t\t\t\t\t\t\t\t\t * sizeof(struct squashfs_fragment_entry));\n\t\t\tif (fragment_table == NULL)\n\t\t\t\tBAD_ERROR(\"Out of memory in save filesystem state\\n\");\n\t\t}\n\n\t\tprintf(\"Appending to existing %d.%d filesystem on %s, block \" \"size %d\\n\", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size);\n\t\tprintf(\"All -b, -noI, -noD, -noF, -noX, no-duplicates, no-fragments, \" \"-always-use-fragments,\\n-exportable and -comp options \" \"ignored\\n\");\n\t\tprintf(\"\\nIf appending is not wanted, please re-run with \" \"-noappend specified!\\n\\n\");\n\n\t\tcompressed_data = (inode_dir_offset + inode_dir_file_size) & ~(SQUASHFS_METADATA_SIZE - 1);\n\t\tuncompressed_data = (inode_dir_offset + inode_dir_file_size) & (SQUASHFS_METADATA_SIZE - 1);\n\n\t\t/* save original filesystem state for restoring ... */\n\t\tsfragments = fragments;\n\t\tsbytes = bytes;\n\t\tsinode_count = sBlk.inodes;\n\t\tscache_bytes = root_inode_offset + root_inode_size;\n\t\tsdirectory_cache_bytes = uncompressed_data;\n\t\tsdata_cache = malloc(scache_bytes);\n\t\tif (sdata_cache == NULL)\n\t\t\tBAD_ERROR(\"Out of memory in save filesystem state\\n\");\n\t\tsdirectory_data_cache = malloc(sdirectory_cache_bytes);\n\t\tif (sdirectory_data_cache == NULL)\n\t\t\tBAD_ERROR(\"Out of memory in save filesystem state\\n\");\n\t\tmemcpy(sdata_cache, data_cache, scache_bytes);\n\t\tmemcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes);\n\t\tsinode_bytes = root_inode_start;\n\t\tstotal_bytes = total_bytes;\n\t\tstotal_inode_bytes = total_inode_bytes;\n\t\tstotal_directory_bytes = total_directory_bytes + compressed_data;\n\t\tsfile_count = file_count;\n\t\tssym_count = sym_count;\n\t\tsdev_count = dev_count;\n\t\tsdir_count = dir_count + 1;\n\t\tsfifo_count = fifo_count;\n\t\tssock_count = sock_count;\n\t\tsdup_files = dup_files;\n\t\tsid_count = id_count;\n\t\twrite_recovery_data(&sBlk);\n\t\tsave_xattrs();\n\t\tappending = TRUE;\n\n\t\t/*\n\t\t * set the filesystem state up to be able to append to the\n\t\t * original filesystem.  The filesystem state differs depending\n\t\t * on whether we're appending to the original root directory, or\n\t\t * if the original root directory becomes a sub-directory\n\t\t * (root-becomes specified on command line, here root_name !=\n\t\t * NULL)\n\t\t */\n\t\tinode_bytes = inode_size = root_inode_start;\n\t\tdirectory_size = last_directory_block;\n\t\tcache_size = root_inode_offset + root_inode_size;\n\t\tdirectory_cache_size = inode_dir_offset + inode_dir_file_size;\n\t\tif (root_name) {\n\t\t\tsdirectory_bytes = last_directory_block;\n\t\t\tsdirectory_compressed_bytes = 0;\n\t\t\troot_inode_number = inode_dir_parent_inode;\n\t\t\tinode_no = sBlk.inodes + 2;\n\t\t\tdirectory_bytes = last_directory_block;\n\t\t\tdirectory_cache_bytes = uncompressed_data;\n\t\t\tmemmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data);\n\t\t\tcache_bytes = root_inode_offset + root_inode_size;\n\t\t\tadd_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE);\n\t\t\ttotal_directory_bytes += compressed_data;\n\t\t\tdir_count++;\n\t\t} else {\n\t\t\tsdirectory_compressed_bytes = last_directory_block - inode_dir_start_block;\n\t\t\tsdirectory_compressed = malloc(sdirectory_compressed_bytes);\n\t\t\tif (sdirectory_compressed == NULL)\n\t\t\t\tBAD_ERROR(\"Out of memory in save filesystem \" \"state\\n\");\n\t\t\tmemcpy(sdirectory_compressed, directory_table + inode_dir_start_block, sdirectory_compressed_bytes);\n\t\t\tsdirectory_bytes = inode_dir_start_block;\n\t\t\troot_inode_number = inode_dir_inode_number;\n\t\t\tinode_no = sBlk.inodes + 1;\n\t\t\tdirectory_bytes = inode_dir_start_block;\n\t\t\tdirectory_cache_bytes = inode_dir_offset;\n\t\t\tcache_bytes = root_inode_offset;\n\t\t}\n\n\t\tinode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count;\n\t}\n\n\tif (path)\n\t\tpaths = add_subdir(paths, path);\n\n\tdump_actions();\n\tdump_pseudos();\n\n\tif (delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode))\n\t\tdir_scan(&inode, source_path[0], scan1_readdir, progress);\n\telse if (!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode))\n\t\tdir_scan(&inode, source_path[0], scan1_single_readdir, progress);\n\telse\n\t\tdir_scan(&inode, \"\", scan1_encomp_readdir, progress);\n\tsBlk.root_inode = inode;\n\tsBlk.inodes = inode_count;\n\tsBlk.s_magic = SQUASHFS_MAGIC;\n\tsBlk.s_major = SQUASHFS_MAJOR;\n\tsBlk.s_minor = SQUASHFS_MINOR;\n\tsBlk.block_size = block_size;\n\tsBlk.block_log = block_log;\n\tsBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, no_fragments, always_use_fragments, duplicate_checking, exportable, no_xattrs, comp_opts);\n\tsBlk.mkfs_time = time(NULL);\n\n\tdisable_info();\n\n\twhile ((fragment = get_frag_action(fragment)))\n\t\twrite_fragment(*fragment);\n\tunlock_fragments();\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &fragment_mutex);\n\tpthread_mutex_lock(&fragment_mutex);\n\twhile (fragments_outstanding) {\n\t\tpthread_mutex_unlock(&fragment_mutex);\n\t\tsched_yield();\n\t\tpthread_mutex_lock(&fragment_mutex);\n\t}\n\tpthread_cleanup_pop(1);\n\n\tqueue_put(to_writer, NULL);\n\tif (queue_get(from_writer) != 0)\n\t\tEXIT_MKSQUASHFS();\n\n\tset_progressbar_state(FALSE);\n\twrite_filesystem_tables(&sBlk, nopad);\n\n\treturn 0;\n}\n"
  },
  {
    "path": "src/squashfs/process_fragments.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * process_fragments.c\n */\n\n#include <pthread.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include <signal.h>\n#include <sys/time.h>\n#include <string.h>\n#include <stdio.h>\n#include <math.h>\n#include <stdarg.h>\n#include <errno.h>\n#include <stdlib.h>\n#include <dirent.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n\n#include \"caches-queues-lists.h\"\n#include \"squashfs_fs.h\"\n#include \"mksquashfs.h\"\n#include \"error.h\"\n#include \"progressbar.h\"\n#include \"info.h\"\n#include \"compressor.h\"\n#include \"process_fragments.h\"\n\n#define FALSE 0\n#define TRUE 1\n\nextern struct queue *to_process_frag;\nextern struct seq_queue *to_main;\nextern int sparse_files;\n\n/*\n * Compute 16 bit BSD checksum over the data, and check for sparseness\n */\nstatic int checksum_sparse(struct file_buffer *file_buffer) {\n\tunsigned char *b = (unsigned char *)file_buffer->data;\n\tunsigned short chksum = 0;\n\tint bytes = file_buffer->size, sparse = TRUE, value;\n\n\twhile (bytes--) {\n\t\tchksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1;\n\t\tvalue = *b++;\n\t\tif (value) {\n\t\t\tsparse = FALSE;\n\t\t\tchksum += value;\n\t\t}\n\t}\n\n\tfile_buffer->checksum = chksum;\n\treturn sparse;\n}\n\nstatic int read_filesystem(int fd, long long byte, int bytes, void *buff) {\n\toff_t off = byte;\n\n\tTRACE(\"read_filesystem: reading from position 0x%llx, bytes %d\\n\", byte, bytes);\n\n\tif (lseek(fd, off, SEEK_SET) == -1) {\n\t\tERROR(\"read_filesystem: Lseek on destination failed because %s, \" \"offset=0x%llx\\n\", strerror(errno), off);\n\t\treturn 0;\n\t} else if (read_bytes(fd, buff, bytes) < bytes) {\n\t\tERROR(\"Read on destination failed\\n\");\n\t\treturn 0;\n\t}\n\n\treturn 1;\n}\n\nstatic struct file_buffer *get_fragment(struct fragment *fragment, char *data_buffer, int fd) {\n\tstruct squashfs_fragment_entry *disk_fragment;\n\tstruct file_buffer *buffer, *compressed_buffer;\n\tlong long start_block;\n\tint res, size, index = fragment->index;\n\tchar locked;\n\n\t/*\n\t * Lookup fragment block in cache.\n\t * If the fragment block doesn't exist, then get the compressed version\n\t * from the writer cache or off disk, and decompress it.\n\t *\n\t * This routine has two things which complicate the code:\n\t *\n\t *  1. Multiple threads can simultaneously lookup/create the\n\t *     same buffer.  This means a buffer needs to be \"locked\"\n\t *     when it is being filled in, to prevent other threads from\n\t *     using it when it is not ready.  This is because we now do\n\t *     fragment duplicate checking in parallel.\n\t *  2. We have two caches which need to be checked for the\n\t *     presence of fragment blocks: the normal fragment cache\n\t *     and a \"reserve\" cache.  The reserve cache is used to\n\t *     prevent an unnecessary pipeline stall when the fragment cache\n\t *     is full of fragments waiting to be compressed.\n\t */\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &dup_mutex);\n\tpthread_mutex_lock(&dup_mutex);\n\n again:\n\tbuffer = cache_lookup_nowait(fragment_buffer, index, &locked);\n\tif (buffer) {\n\t\tpthread_mutex_unlock(&dup_mutex);\n\t\tif (locked)\n\t\t\t/* got a buffer being filled in.  Wait for it */\n\t\t\tcache_wait_unlock(buffer);\n\t\tgoto finished;\n\t}\n\n\t/* not in fragment cache, is it in the reserve cache? */\n\tbuffer = cache_lookup_nowait(reserve_cache, index, &locked);\n\tif (buffer) {\n\t\tpthread_mutex_unlock(&dup_mutex);\n\t\tif (locked)\n\t\t\t/* got a buffer being filled in.  Wait for it */\n\t\t\tcache_wait_unlock(buffer);\n\t\tgoto finished;\n\t}\n\n\t/* in neither cache, try to get it from the fragment cache */\n\tbuffer = cache_get_nowait(fragment_buffer, index);\n\tif (!buffer) {\n\t\t/*\n\t\t * no room, get it from the reserve cache, this is\n\t\t * dimensioned so it will always have space (no more than\n\t\t * processors + 1 can have an outstanding reserve buffer)\n\t\t */\n\t\tbuffer = cache_get_nowait(reserve_cache, index);\n\t\tif (!buffer) {\n\t\t\t/* failsafe */\n\t\t\tERROR(\"no space in reserve cache\\n\");\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\tpthread_mutex_unlock(&dup_mutex);\n\n\tcompressed_buffer = cache_lookup(fwriter_buffer, index);\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &fragment_mutex);\n\tpthread_mutex_lock(&fragment_mutex);\n\tdisk_fragment = &fragment_table[index];\n\tsize = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size);\n\tstart_block = disk_fragment->start_block;\n\tpthread_cleanup_pop(1);\n\n\tif (SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) {\n\t\tint error;\n\t\tchar *data;\n\n\t\tif (compressed_buffer)\n\t\t\tdata = compressed_buffer->data;\n\t\telse {\n\t\t\tres = read_filesystem(fd, start_block, size, data_buffer);\n\t\t\tif (res == 0) {\n\t\t\t\tERROR(\"Failed to read fragment from output\" \" filesystem\\n\");\n\t\t\t\tBAD_ERROR(\"Output filesystem corrupted?\\n\");\n\t\t\t}\n\t\t\tdata = data_buffer;\n\t\t}\n\n\t\tres = compressor_uncompress(comp, buffer->data, data, size, block_size, &error);\n\t\tif (res == -1)\n\t\t\tBAD_ERROR(\"%s uncompress failed with error code %d\\n\", comp->name, error);\n\t} else if (compressed_buffer)\n\t\tmemcpy(buffer->data, compressed_buffer->data, size);\n\telse {\n\t\tres = read_filesystem(fd, start_block, size, buffer->data);\n\t\tif (res == 0) {\n\t\t\tERROR(\"Failed to read fragment from output \" \"filesystem\\n\");\n\t\t\tBAD_ERROR(\"Output filesystem corrupted?\\n\");\n\t\t}\n\t}\n\n\tcache_unlock(buffer);\n\tcache_block_put(compressed_buffer);\n\n finished:\n\tpthread_cleanup_pop(0);\n\n\treturn buffer;\n}\n\nstruct file_buffer *get_fragment_cksum(struct file_info *file, char *data_buffer, int fd, unsigned short *checksum) {\n\tstruct file_buffer *frag_buffer;\n\tstruct append_file *append;\n\tint index = file->fragment->index;\n\n\tfrag_buffer = get_fragment(file->fragment, data_buffer, fd);\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &dup_mutex);\n\n\tfor (append = file_mapping[index]; append; append = append->next) {\n\t\tint offset = append->file->fragment->offset;\n\t\tint size = append->file->fragment->size;\n\t\tchar *data = frag_buffer->data + offset;\n\t\tunsigned short cksum = get_checksum_mem(data, size);\n\n\t\tif (file == append->file)\n\t\t\t*checksum = cksum;\n\n\t\tpthread_mutex_lock(&dup_mutex);\n\t\tappend->file->fragment_checksum = cksum;\n\t\tappend->file->have_frag_checksum = TRUE;\n\t\tpthread_mutex_unlock(&dup_mutex);\n\t}\n\n\tpthread_cleanup_pop(0);\n\n\treturn frag_buffer;\n}\n\nvoid *frag_thrd(void *destination_file) {\n\tsigset_t sigmask, old_mask;\n\tchar *data_buffer;\n\tint fd;\n\n\tsigemptyset(&sigmask);\n\tsigaddset(&sigmask, SIGINT);\n\tsigaddset(&sigmask, SIGTERM);\n\tsigaddset(&sigmask, SIGUSR1);\n\tpthread_sigmask(SIG_BLOCK, &sigmask, &old_mask);\n\n\tfd = open(destination_file, O_RDONLY);\n\tif (fd == -1)\n\t\tBAD_ERROR(\"frag_thrd: can't open destination for reading\\n\");\n\n\tdata_buffer = malloc(SQUASHFS_FILE_MAX_SIZE);\n\tif (data_buffer == NULL)\n\t\tMEM_ERROR();\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &dup_mutex);\n\n\twhile (1) {\n\t\tstruct file_buffer *file_buffer = queue_get(to_process_frag);\n\t\tstruct file_buffer *buffer;\n\t\tint sparse = checksum_sparse(file_buffer);\n\t\tstruct file_info *dupl_ptr;\n\t\tlong long file_size;\n\t\tunsigned short checksum;\n\t\tchar flag;\n\t\tint res;\n\n\t\tif (sparse_files && sparse) {\n\t\t\tfile_buffer->c_byte = 0;\n\t\t\tfile_buffer->fragment = FALSE;\n\t\t} else\n\t\t\tfile_buffer->c_byte = file_buffer->size;\n\n\t\t/*\n\t\t * Specutively pull into the fragment cache any fragment blocks\n\t\t * which contain fragments which *this* fragment may be\n\t\t * be a duplicate.\n\t\t *\n\t\t * By ensuring the fragment block is in cache ahead of time\n\t\t * should eliminate the parallelisation stall when the\n\t\t * main thread needs to read the fragment block to do a\n\t\t * duplicate check on it.\n\t\t *\n\t\t * If this is a fragment belonging to a larger file\n\t\t * (with additional blocks) then ignore it.  Here we're\n\t\t * interested in the \"low hanging fruit\" of files which\n\t\t * consist of only a fragment\n\t\t */\n\t\tif (file_buffer->file_size != file_buffer->size) {\n\t\t\tseq_queue_put(to_main, file_buffer);\n\t\t\tcontinue;\n\t\t}\n\n\t\tfile_size = file_buffer->file_size;\n\n\t\tpthread_mutex_lock(&dup_mutex);\n\t\tdupl_ptr = dupl[DUP_HASH(file_size)];\n\t\tpthread_mutex_unlock(&dup_mutex);\n\n\t\tfile_buffer->dupl_start = dupl_ptr;\n\t\tfile_buffer->duplicate = FALSE;\n\n\t\tfor (; dupl_ptr; dupl_ptr = dupl_ptr->next) {\n\t\t\tif (file_size != dupl_ptr->file_size || file_size != dupl_ptr->fragment->size)\n\t\t\t\tcontinue;\n\n\t\t\tpthread_mutex_lock(&dup_mutex);\n\t\t\tflag = dupl_ptr->have_frag_checksum;\n\t\t\tchecksum = dupl_ptr->fragment_checksum;\n\t\t\tpthread_mutex_unlock(&dup_mutex);\n\n\t\t\t/*\n\t\t\t * If we have the checksum and it matches then\n\t\t\t * read in the fragment block.\n\t\t\t *\n\t\t\t * If we *don't* have the checksum, then we are\n\t\t\t * appending, and the fragment block is on the\n\t\t\t * \"old\" filesystem.  Read it in and checksum\n\t\t\t * the entire fragment buffer\n\t\t\t */\n\t\t\tif (!flag) {\n\t\t\t\tbuffer = get_fragment_cksum(dupl_ptr, data_buffer, fd, &checksum);\n\t\t\t\tif (checksum != file_buffer->checksum) {\n\t\t\t\t\tcache_block_put(buffer);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if (checksum == file_buffer->checksum)\n\t\t\t\tbuffer = get_fragment(dupl_ptr->fragment, data_buffer, fd);\n\t\t\telse\n\t\t\t\tcontinue;\n\n\t\t\tres = memcmp(file_buffer->data, buffer->data + dupl_ptr->fragment->offset, file_size);\n\t\t\tcache_block_put(buffer);\n\t\t\tif (res == 0) {\n\t\t\t\tstruct file_buffer *dup = malloc(sizeof(*dup));\n\t\t\t\tif (dup == NULL)\n\t\t\t\t\tMEM_ERROR();\n\t\t\t\tmemcpy(dup, file_buffer, sizeof(*dup));\n\t\t\t\tcache_block_put(file_buffer);\n\t\t\t\tdup->dupl_start = dupl_ptr;\n\t\t\t\tdup->duplicate = TRUE;\n\t\t\t\tfile_buffer = dup;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tseq_queue_put(to_main, file_buffer);\n\t}\n\n\tpthread_cleanup_pop(0);\n}\n"
  },
  {
    "path": "src/squashfs/progressbar.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * progressbar.c\n */\n\n#include <pthread.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include <signal.h>\n#include <sys/time.h>\n#include <stdio.h>\n#include <math.h>\n#include <stdarg.h>\n#include <errno.h>\n#include <stdlib.h>\n\n#include \"error.h\"\n\n#define FALSE 0\n#define TRUE 1\n\n/* flag whether progressbar display is enabled or not */\nint display_progress_bar = FALSE;\n\n/* flag whether the progress bar is temporarily disbled */\nint temp_disabled = FALSE;\n\nint rotate = 0;\nint cur_uncompressed = 0, estimated_uncompressed = 0;\nint columns;\n\npthread_t progress_thread;\npthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER;\n\nstatic void sigwinch_handler() {\n\tstruct winsize winsize;\n\n\tif (ioctl(1, TIOCGWINSZ, &winsize) == -1) {\n\t\tif (isatty(STDOUT_FILENO))\n\t\t\tERROR(\"TIOCGWINSZ ioctl failed, defaulting to 80 \" \"columns\\n\");\n\t\tcolumns = 80;\n\t} else\n\t\tcolumns = winsize.ws_col;\n}\n\nstatic void sigalrm_handler() {\n\trotate = (rotate + 1) % 4;\n}\n\nvoid inc_progress_bar() {\n\tcur_uncompressed++;\n}\n\nvoid dec_progress_bar(int count) {\n\tcur_uncompressed -= count;\n}\n\nvoid progress_bar_size(int count) {\n\testimated_uncompressed += count;\n}\n\nstatic void progress_bar(long long current, long long max, int columns) {\n\tchar rotate_list[] = { '|', '/', '-', '\\\\' };\n\tint max_digits, used, hashes, spaces;\n\tstatic int tty = -1;\n\n\tif (max == 0)\n\t\treturn;\n\n\tmax_digits = floor(log10(max)) + 1;\n\tused = max_digits * 2 + 11;\n\thashes = (current * (columns - used)) / max;\n\tspaces = columns - used - hashes;\n\n\tif ((current > max) || (columns - used < 0))\n\t\treturn;\n\n\tif (tty == -1)\n\t\ttty = isatty(STDOUT_FILENO);\n\tif (!tty) {\n\t\tstatic long long previous = -1;\n\n\t\t/* Updating much more frequently than this results in huge\n\t\t * log files. */\n\t\tif ((current % 100) != 0 && current != max)\n\t\t\treturn;\n\t\t/* Don't update just to rotate the spinner. */\n\t\tif (current == previous)\n\t\t\treturn;\n\t\tprevious = current;\n\t}\n\n\tprintf(\"\\r[\");\n\n\twhile (hashes--)\n\t\tputchar('=');\n\n\tputchar(rotate_list[rotate]);\n\n\twhile (spaces--)\n\t\tputchar(' ');\n\n\tprintf(\"] %*lld/%*lld\", max_digits, current, max_digits, max);\n\tprintf(\" %3lld%%\", current * 100 / max);\n\tfflush(stdout);\n}\n\nvoid enable_progress_bar() {\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &progress_mutex);\n\tpthread_mutex_lock(&progress_mutex);\n\tif (display_progress_bar)\n\t\tprogress_bar(cur_uncompressed, estimated_uncompressed, columns);\n\ttemp_disabled = FALSE;\n\tpthread_cleanup_pop(1);\n}\n\nvoid disable_progress_bar() {\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &progress_mutex);\n\tpthread_mutex_lock(&progress_mutex);\n\tif (display_progress_bar)\n\t\tprintf(\"\\n\");\n\ttemp_disabled = TRUE;\n\tpthread_cleanup_pop(1);\n}\n\nvoid set_progressbar_state(int state) {\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &progress_mutex);\n\tpthread_mutex_lock(&progress_mutex);\n\tif (display_progress_bar != state) {\n\t\tif (display_progress_bar && !temp_disabled) {\n\t\t\tprogress_bar(cur_uncompressed, estimated_uncompressed, columns);\n\t\t\tprintf(\"\\n\");\n\t\t}\n\t\tdisplay_progress_bar = state;\n\t}\n\tpthread_cleanup_pop(1);\n}\n\nvoid *progress_thrd(void *arg) {\n\tstruct timespec requested_time, remaining;\n\tstruct itimerval itimerval;\n\tstruct winsize winsize;\n\n\tif (ioctl(1, TIOCGWINSZ, &winsize) == -1) {\n\t\tif (isatty(STDOUT_FILENO))\n\t\t\tERROR(\"TIOCGWINSZ ioctl failed, defaulting to 80 \" \"columns\\n\");\n\t\tcolumns = 80;\n\t} else\n\t\tcolumns = winsize.ws_col;\n\tsignal(SIGWINCH, sigwinch_handler);\n\tsignal(SIGALRM, sigalrm_handler);\n\n\titimerval.it_value.tv_sec = 0;\n\titimerval.it_value.tv_usec = 250000;\n\titimerval.it_interval.tv_sec = 0;\n\titimerval.it_interval.tv_usec = 250000;\n\tsetitimer(ITIMER_REAL, &itimerval, NULL);\n\n\trequested_time.tv_sec = 0;\n\trequested_time.tv_nsec = 250000000;\n\n\twhile (1) {\n\t\tint res = nanosleep(&requested_time, &remaining);\n\n\t\tif (res == -1 && errno != EINTR)\n\t\t\tBAD_ERROR(\"nanosleep failed in progress thread\\n\");\n\n\t\tpthread_mutex_lock(&progress_mutex);\n\t\tif (display_progress_bar && !temp_disabled)\n\t\t\tprogress_bar(cur_uncompressed, estimated_uncompressed, columns);\n\t\tpthread_mutex_unlock(&progress_mutex);\n\t}\n}\n\nvoid init_progress_bar() {\n\tpthread_create(&progress_thread, NULL, progress_thrd, NULL);\n}\n\nvoid progressbar_error(char *fmt, ...) {\n\tva_list ap;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &progress_mutex);\n\tpthread_mutex_lock(&progress_mutex);\n\n\tif (display_progress_bar && !temp_disabled)\n\t\tfprintf(stderr, \"\\n\");\n\n\tva_start(ap, fmt);\n\tvfprintf(stderr, fmt, ap);\n\tva_end(ap);\n\n\tpthread_cleanup_pop(1);\n}\n\nvoid progressbar_info(char *fmt, ...) {\n\tva_list ap;\n\n\tpthread_cleanup_push((void *)pthread_mutex_unlock, &progress_mutex);\n\tpthread_mutex_lock(&progress_mutex);\n\n\tif (display_progress_bar && !temp_disabled)\n\t\tprintf(\"\\n\");\n\n\tva_start(ap, fmt);\n\tvprintf(fmt, ap);\n\tva_end(ap);\n\n\tpthread_cleanup_pop(1);\n}\n"
  },
  {
    "path": "src/squashfs/pseudo.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2009, 2010, 2012, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * pseudo.c\n */\n\n#include <pwd.h>\n#include <grp.h>\n#include <unistd.h>\n#include <stdio.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <string.h>\n#include <stdlib.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <ctype.h>\n\n#include \"pseudo.h\"\n#include \"error.h\"\n#include \"progressbar.h\"\n\n#define TRUE 1\n#define FALSE 0\n\nextern int read_file(char *filename, char *type, int (parse_line) (char *));\n\nstruct pseudo_dev **pseudo_file = NULL;\nstruct pseudo *pseudo = NULL;\nint pseudo_count = 0;\n\nstatic char *get_component(char *target, char **targname) {\n\tchar *start;\n\n\twhile (*target == '/')\n\t\ttarget++;\n\n\tstart = target;\n\twhile (*target != '/' && *target != '\\0')\n\t\ttarget++;\n\n\t*targname = strndup(start, target - start);\n\n\twhile (*target == '/')\n\t\ttarget++;\n\n\treturn target;\n}\n\n/*\n * Add pseudo device target to the set of pseudo devices.  Pseudo_dev\n * describes the pseudo device attributes.\n */\nstruct pseudo *add_pseudo(struct pseudo *pseudo, struct pseudo_dev *pseudo_dev, char *target, char *alltarget) {\n\tchar *targname;\n\tint i;\n\n\ttarget = get_component(target, &targname);\n\n\tif (pseudo == NULL) {\n\t\tpseudo = malloc(sizeof(struct pseudo));\n\t\tif (pseudo == NULL)\n\t\t\tMEM_ERROR();\n\n\t\tpseudo->names = 0;\n\t\tpseudo->count = 0;\n\t\tpseudo->name = NULL;\n\t}\n\n\tfor (i = 0; i < pseudo->names; i++)\n\t\tif (strcmp(pseudo->name[i].name, targname) == 0)\n\t\t\tbreak;\n\n\tif (i == pseudo->names) {\n\t\t/* allocate new name entry */\n\t\tpseudo->names++;\n\t\tpseudo->name = realloc(pseudo->name, (i + 1) * sizeof(struct pseudo_entry));\n\t\tif (pseudo->name == NULL)\n\t\t\tMEM_ERROR();\n\t\tpseudo->name[i].name = targname;\n\n\t\tif (target[0] == '\\0') {\n\t\t\t/* at leaf pathname component */\n\t\t\tpseudo->name[i].pseudo = NULL;\n\t\t\tpseudo->name[i].pathname = strdup(alltarget);\n\t\t\tpseudo->name[i].dev = pseudo_dev;\n\t\t} else {\n\t\t\t/* recurse adding child components */\n\t\t\tpseudo->name[i].dev = NULL;\n\t\t\tpseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget);\n\t\t}\n\t} else {\n\t\t/* existing matching entry */\n\t\tfree(targname);\n\n\t\tif (pseudo->name[i].pseudo == NULL) {\n\t\t\t/* No sub-directory which means this is the leaf\n\t\t\t * component of a pre-existing pseudo file.\n\t\t\t */\n\t\t\tif (target[0] != '\\0') {\n\t\t\t\t/*\n\t\t\t\t * entry must exist as either a 'd' type or\n\t\t\t\t * 'm' type pseudo file\n\t\t\t\t */\n\t\t\t\tif (pseudo->name[i].dev->type == 'd' || pseudo->name[i].dev->type == 'm')\n\t\t\t\t\t/* recurse adding child components */\n\t\t\t\t\tpseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget);\n\t\t\t\telse {\n\t\t\t\t\tERROR_START(\"%s already exists as a \" \"non directory.\", pseudo->name[i].name);\n\t\t\t\t\tERROR_EXIT(\".  Ignoring %s!\\n\", alltarget);\n\t\t\t\t}\n\t\t\t} else if (memcmp(pseudo_dev, pseudo->name[i].dev, sizeof(struct pseudo_dev)) != 0) {\n\t\t\t\tERROR_START(\"%s already exists as a different \" \"pseudo definition.\", alltarget);\n\t\t\t\tERROR_EXIT(\"  Ignoring!\\n\");\n\t\t\t} else {\n\t\t\t\tERROR_START(\"%s already exists as an identical \" \"pseudo definition!\", alltarget);\n\t\t\t\tERROR_EXIT(\"  Ignoring!\\n\");\n\t\t\t}\n\t\t} else {\n\t\t\tif (target[0] == '\\0') {\n\t\t\t\t/*\n\t\t\t\t * sub-directory exists, which means we can only\n\t\t\t\t * add a pseudo file of type 'd' or type 'm'\n\t\t\t\t */\n\t\t\t\tif (pseudo->name[i].dev == NULL && (pseudo_dev->type == 'd' || pseudo_dev->type == 'm')) {\n\t\t\t\t\tpseudo->name[i].pathname = strdup(alltarget);\n\t\t\t\t\tpseudo->name[i].dev = pseudo_dev;\n\t\t\t\t} else {\n\t\t\t\t\tERROR_START(\"%s already exists as a \" \"different pseudo definition.\", pseudo->name[i].name);\n\t\t\t\t\tERROR_EXIT(\"  Ignoring %s!\\n\", alltarget);\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\t/* recurse adding child components */\n\t\t\t\tadd_pseudo(pseudo->name[i].pseudo, pseudo_dev, target, alltarget);\n\t\t}\n\t}\n\n\treturn pseudo;\n}\n\n/*\n * Find subdirectory in pseudo directory referenced by pseudo, matching\n * filename.  If filename doesn't exist or if filename is a leaf file\n * return NULL\n */\nstruct pseudo *pseudo_subdir(char *filename, struct pseudo *pseudo) {\n\tint i;\n\n\tif (pseudo == NULL)\n\t\treturn NULL;\n\n\tfor (i = 0; i < pseudo->names; i++)\n\t\tif (strcmp(filename, pseudo->name[i].name) == 0)\n\t\t\treturn pseudo->name[i].pseudo;\n\n\treturn NULL;\n}\n\nstruct pseudo_entry *pseudo_readdir(struct pseudo *pseudo) {\n\tif (pseudo == NULL)\n\t\treturn NULL;\n\n\twhile (pseudo->count < pseudo->names) {\n\t\tif (pseudo->name[pseudo->count].dev != NULL)\n\t\t\treturn &pseudo->name[pseudo->count++];\n\t\telse\n\t\t\tpseudo->count++;\n\t}\n\n\treturn NULL;\n}\n\nint pseudo_exec_file(struct pseudo_dev *dev, int *child) {\n\tint res, pipefd[2];\n\n\tres = pipe(pipefd);\n\tif (res == -1) {\n\t\tERROR(\"Executing dynamic pseudo file, pipe failed\\n\");\n\t\treturn 0;\n\t}\n\n\t*child = fork();\n\tif (*child == -1) {\n\t\tERROR(\"Executing dynamic pseudo file, fork failed\\n\");\n\t\tgoto failed;\n\t}\n\n\tif (*child == 0) {\n\t\tclose(pipefd[0]);\n\t\tclose(STDOUT_FILENO);\n\t\tres = dup(pipefd[1]);\n\t\tif (res == -1)\n\t\t\texit(EXIT_FAILURE);\n\n\t\texecl(\"/bin/sh\", \"sh\", \"-c\", dev->command, (char *)NULL);\n\t\texit(EXIT_FAILURE);\n\t}\n\n\tclose(pipefd[1]);\n\treturn pipefd[0];\n\n failed:\n\tclose(pipefd[0]);\n\tclose(pipefd[1]);\n\treturn 0;\n}\n\nvoid add_pseudo_file(struct pseudo_dev *dev) {\n\tpseudo_file = realloc(pseudo_file, (pseudo_count + 1) * sizeof(struct pseudo_dev *));\n\tif (pseudo_file == NULL)\n\t\tMEM_ERROR();\n\n\tdev->pseudo_id = pseudo_count;\n\tpseudo_file[pseudo_count++] = dev;\n}\n\nstruct pseudo_dev *get_pseudo_file(int pseudo_id) {\n\treturn pseudo_file[pseudo_id];\n}\n\nint read_pseudo_def(char *def) {\n\tint n, bytes;\n\tunsigned int major = 0, minor = 0, mode;\n\tchar type, *ptr;\n\tchar suid[100], sgid[100];\t/* overflow safe */\n\tchar *filename, *name;\n\tchar *orig_def = def;\n\tlong long uid, gid;\n\tstruct pseudo_dev *dev;\n\n\t/*\n\t * Scan for filename, don't use sscanf() and \"%s\" because\n\t * that can't handle filenames with spaces\n\t */\n\tfilename = malloc(strlen(def) + 1);\n\tif (filename == NULL)\n\t\tMEM_ERROR();\n\n\tfor (name = filename; !isspace(*def) && *def != '\\0';) {\n\t\tif (*def == '\\\\') {\n\t\t\tdef++;\n\t\t\tif (*def == '\\0')\n\t\t\t\tbreak;\n\t\t}\n\t\t*name++ = *def++;\n\t}\n\t*name = '\\0';\n\n\tif (*filename == '\\0') {\n\t\tERROR(\"Not enough or invalid arguments in pseudo file \" \"definition \\\"%s\\\"\\n\", orig_def);\n\t\tgoto error;\n\t}\n\n\tn = sscanf(def, \" %c %o %99s %99s %n\", &type, &mode, suid, sgid, &bytes);\n\tdef += bytes;\n\n\tif (n < 4) {\n\t\tERROR(\"Not enough or invalid arguments in pseudo file \" \"definition \\\"%s\\\"\\n\", orig_def);\n\t\tswitch (n) {\n\t\tcase -1:\n\t\t\t/* FALLTHROUGH */\n\t\tcase 0:\n\t\t\tERROR(\"Read filename, but failed to read or match \" \"type\\n\");\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tERROR(\"Read filename and type, but failed to read or \" \"match octal mode\\n\");\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tERROR(\"Read filename, type and mode, but failed to \" \"read or match uid\\n\");\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tERROR(\"Read filename, type, mode and uid, but failed \" \"to read or match gid\\n\");\n\t\t\tbreak;\n\t\t}\n\t\tgoto error;\n\t}\n\n\tswitch (type) {\n\tcase 'b':\n\t\t/* FALLTHROUGH */\n\tcase 'c':\n\t\tn = sscanf(def, \"%u %u %n\", &major, &minor, &bytes);\n\t\tdef += bytes;\n\n\t\tif (n < 2) {\n\t\t\tERROR(\"Not enough or invalid arguments in %s device \" \"pseudo file definition \\\"%s\\\"\\n\", type == 'b' ? \"block\" : \"character\", orig_def);\n\t\t\tif (n < 1)\n\t\t\t\tERROR(\"Read filename, type, mode, uid and gid, \" \"but failed to read or match major\\n\");\n\t\t\telse\n\t\t\t\tERROR(\"Read filename, type, mode, uid, gid \" \"and major, but failed to read  or \" \"match minor\\n\");\n\t\t\tgoto error;\n\t\t}\n\n\t\tif (major > 0xfff) {\n\t\t\tERROR(\"Major %d out of range\\n\", major);\n\t\t\tgoto error;\n\t\t}\n\n\t\tif (minor > 0xfffff) {\n\t\t\tERROR(\"Minor %d out of range\\n\", minor);\n\t\t\tgoto error;\n\t\t}\n\t\t/* FALLTHROUGH */\n\tcase 'd':\n\t\t/* FALLTHROUGH */\n\tcase 'm':\n\t\t/*\n\t\t * Check for trailing junk after expected arguments\n\t\t */\n\t\tif (def[0] != '\\0') {\n\t\t\tERROR(\"Unexpected tailing characters in pseudo file \" \"definition \\\"%s\\\"\\n\", orig_def);\n\t\t\tgoto error;\n\t\t}\n\t\tbreak;\n\tcase 'f':\n\t\tif (def[0] == '\\0') {\n\t\t\tERROR(\"Not enough arguments in dynamic file pseudo \" \"definition \\\"%s\\\"\\n\", orig_def);\n\t\t\tERROR(\"Expected command, which can be an executable \" \"or a piece of shell script\\n\");\n\t\t\tgoto error;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tERROR(\"Unsupported type %c\\n\", type);\n\t\tgoto error;\n\t}\n\n\tif (mode > 07777) {\n\t\tERROR(\"Mode %o out of range\\n\", mode);\n\t\tgoto error;\n\t}\n\n\tuid = strtoll(suid, &ptr, 10);\n\tif (*ptr == '\\0') {\n\t\tif (uid < 0 || uid > ((1LL << 32) - 1)) {\n\t\t\tERROR(\"Uid %s out of range\\n\", suid);\n\t\t\tgoto error;\n\t\t}\n\t} else {\n\t\tstruct passwd *pwuid = getpwnam(suid);\n\t\tif (pwuid)\n\t\t\tuid = pwuid->pw_uid;\n\t\telse {\n\t\t\tERROR(\"Uid %s invalid uid or unknown user\\n\", suid);\n\t\t\tgoto error;\n\t\t}\n\t}\n\n\tgid = strtoll(sgid, &ptr, 10);\n\tif (*ptr == '\\0') {\n\t\tif (gid < 0 || gid > ((1LL << 32) - 1)) {\n\t\t\tERROR(\"Gid %s out of range\\n\", sgid);\n\t\t\tgoto error;\n\t\t}\n\t} else {\n\t\tstruct group *grgid = getgrnam(sgid);\n\t\tif (grgid)\n\t\t\tgid = grgid->gr_gid;\n\t\telse {\n\t\t\tERROR(\"Gid %s invalid uid or unknown user\\n\", sgid);\n\t\t\tgoto error;\n\t\t}\n\t}\n\n\tswitch (type) {\n\tcase 'b':\n\t\tmode |= S_IFBLK;\n\t\tbreak;\n\tcase 'c':\n\t\tmode |= S_IFCHR;\n\t\tbreak;\n\tcase 'd':\n\t\tmode |= S_IFDIR;\n\t\tbreak;\n\tcase 'f':\n\t\tmode |= S_IFREG;\n\t\tbreak;\n\t}\n\n\tdev = malloc(sizeof(struct pseudo_dev));\n\tif (dev == NULL)\n\t\tMEM_ERROR();\n\n\tdev->type = type;\n\tdev->mode = mode;\n\tdev->uid = uid;\n\tdev->gid = gid;\n\tdev->major = major;\n\tdev->minor = minor;\n\tif (type == 'f') {\n\t\tdev->command = strdup(def);\n\t\tadd_pseudo_file(dev);\n\t}\n\n\tpseudo = add_pseudo(pseudo, dev, filename, filename);\n\n\tfree(filename);\n\treturn TRUE;\n\n error:\n\tERROR(\"Pseudo definitions should be of format\\n\");\n\tERROR(\"\\tfilename d mode uid gid\\n\");\n\tERROR(\"\\tfilename m mode uid gid\\n\");\n\tERROR(\"\\tfilename b mode uid gid major minor\\n\");\n\tERROR(\"\\tfilename c mode uid gid major minor\\n\");\n\tERROR(\"\\tfilename f mode uid command\\n\");\n\tfree(filename);\n\treturn FALSE;\n}\n\nint read_pseudo_file(char *filename) {\n\treturn read_file(filename, \"pseudo\", read_pseudo_def);\n}\n\nstruct pseudo *get_pseudo() {\n\treturn pseudo;\n}\n\n#ifdef SQUASHFS_TRACE\nstatic void dump_pseudo(struct pseudo *pseudo, char *string) {\n\tint i, res;\n\tchar *path;\n\n\tfor (i = 0; i < pseudo->names; i++) {\n\t\tstruct pseudo_entry *entry = &pseudo->name[i];\n\t\tif (string) {\n\t\t\tres = asprintf(&path, \"%s/%s\", string, entry->name);\n\t\t\tif (res == -1)\n\t\t\t\tBAD_ERROR(\"asprintf failed in dump_pseudo\\n\");\n\t\t} else\n\t\t\tpath = entry->name;\n\t\tif (entry->dev)\n\t\t\tERROR(\"%s %c 0%o %d %d %d %d\\n\", path, entry->dev->type, entry->dev->mode & ~S_IFMT, entry->dev->uid, entry->dev->gid, entry->dev->major, entry->dev->minor);\n\t\tif (entry->pseudo)\n\t\t\tdump_pseudo(entry->pseudo, path);\n\t\tif (string)\n\t\t\tfree(path);\n\t}\n}\n\nvoid dump_pseudos() {\n\tdump_pseudo(pseudo, NULL);\n}\n#else\nvoid dump_pseudos() {\n}\n#endif\n"
  },
  {
    "path": "src/squashfs/read_file.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2012\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * read_file.c\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <errno.h>\n\n#include \"error.h\"\n\n#define TRUE 1\n#define FALSE 0\n#define MAX_LINE 16384\n\n/*\n * Read file, passing each line to parse_line() for\n * parsing.\n *\n * Lines can be split across multiple lines using \"\\\".\n *\n * Blank lines and comment lines indicated by # are supported.\n */\nint read_file(char *filename, char *type, int (parse_line) (char *)) {\n\tFILE *fd;\n\tchar *def, *err, *line = NULL;\n\tint res, size = 0;\n\n\tfd = fopen(filename, \"r\");\n\tif (fd == NULL) {\n\t\tERROR(\"Could not open %s device file \\\"%s\\\" because %s\\n\", type, filename, strerror(errno));\n\t\treturn FALSE;\n\t}\n\n\twhile (1) {\n\t\tint total = 0;\n\n\t\twhile (1) {\n\t\t\tint len;\n\n\t\t\tif (total + (MAX_LINE + 1) > size) {\n\t\t\t\tline = realloc(line, size += (MAX_LINE + 1));\n\t\t\t\tif (line == NULL)\n\t\t\t\t\tMEM_ERROR();\n\t\t\t}\n\n\t\t\terr = fgets(line + total, MAX_LINE + 1, fd);\n\t\t\tif (err == NULL)\n\t\t\t\tbreak;\n\n\t\t\tlen = strlen(line + total);\n\t\t\ttotal += len;\n\n\t\t\tif (len == MAX_LINE && line[total - 1] != '\\n') {\n\t\t\t\t/* line too large */\n\t\t\t\tERROR(\"Line too long when reading \" \"%s file \\\"%s\\\", larger than \" \"%d bytes\\n\", type, filename, MAX_LINE);\n\t\t\t\tgoto failed;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Remove '\\n' terminator if it exists (the last line\n\t\t\t * in the file may not be '\\n' terminated)\n\t\t\t */\n\t\t\tif (len && line[total - 1] == '\\n') {\n\t\t\t\tline[--total] = '\\0';\n\t\t\t\tlen--;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * If no line continuation then jump out to\n\t\t\t * process line.  Note, we have to be careful to\n\t\t\t * check for \"\\\\\" (backslashed backslash) and to\n\t\t\t * ensure we don't look at the previous line\n\t\t\t */\n\t\t\tif (len == 0 || line[total - 1] != '\\\\' || (len >= 2 && strcmp(line + total - 2, \"\\\\\\\\\") == 0))\n\t\t\t\tbreak;\n\t\t\telse\n\t\t\t\ttotal--;\n\t\t}\n\n\t\tif (err == NULL) {\n\t\t\tif (ferror(fd)) {\n\t\t\t\tERROR(\"Reading %s file \\\"%s\\\" failed \" \"because %s\\n\", type, filename, strerror(errno));\n\t\t\t\tgoto failed;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * At EOF, normally we'll be finished, but, have to\n\t\t\t * check for special case where we had \"\\\" line\n\t\t\t * continuation and then hit EOF immediately afterwards\n\t\t\t */\n\t\t\tif (total == 0)\n\t\t\t\tbreak;\n\t\t\telse\n\t\t\t\tline[total] = '\\0';\n\t\t}\n\n\t\t/* Skip any leading whitespace */\n\t\tfor (def = line; isspace(*def); def++) ;\n\n\t\t/* if line is now empty after skipping characters, skip it */\n\t\tif (*def == '\\0')\n\t\t\tcontinue;\n\n\t\t/* if comment line, skip */\n\t\tif (*def == '#')\n\t\t\tcontinue;\n\n\t\tres = parse_line(def);\n\t\tif (res == FALSE)\n\t\t\tgoto failed;\n\t}\n\n\tfclose(fd);\n\tfree(line);\n\treturn TRUE;\n\n failed:\n\tfclose(fd);\n\tfree(line);\n\treturn FALSE;\n}\n"
  },
  {
    "path": "src/squashfs/read_fs.c",
    "content": "/*\n * Read a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,\n * 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * read_fs.c\n */\n\n#define TRUE 1\n#define FALSE 0\n#include <stdio.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <limits.h>\n#include <dirent.h>\n\n#if !defined(linux) && !defined(__CYGWIN__)\n#    define __BYTE_ORDER BYTE_ORDER\n#    define __BIG_ENDIAN BIG_ENDIAN\n#    define __LITTLE_ENDIAN LITTLE_ENDIAN\n#else\n#    include <endian.h>\n#endif\n\n#include <stdlib.h>\n\n#include \"squashfs_fs.h\"\n#include \"squashfs_swap.h\"\n#include \"compressor.h\"\n#include \"xattr.h\"\n#include \"error.h\"\n#include \"mksquashfs.h\"\n\nint read_block(int fd, long long start, long long *next, int expected, void *block) {\n\tunsigned short c_byte;\n\tint res, compressed;\n\tint outlen = expected ? expected : SQUASHFS_METADATA_SIZE;\n\n\t/* Read block size */\n\tres = read_fs_bytes(fd, start, 2, &c_byte);\n\tif (res == 0)\n\t\treturn 0;\n\n\tSQUASHFS_INSWAP_SHORTS(&c_byte, 1);\n\tcompressed = SQUASHFS_COMPRESSED(c_byte);\n\tc_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);\n\n\t/*\n\t * The block size should not be larger than\n\t * the uncompressed size (or max uncompressed size if\n\t * expected is 0)\n\t */\n\tif (c_byte > outlen)\n\t\treturn 0;\n\n\tif (compressed) {\n\t\tchar buffer[c_byte];\n\t\tint error;\n\n\t\tres = read_fs_bytes(fd, start + 2, c_byte, buffer);\n\t\tif (res == 0)\n\t\t\treturn 0;\n\n\t\tres = compressor_uncompress(comp, block, buffer, c_byte, outlen, &error);\n\t\tif (res == -1) {\n\t\t\tERROR(\"%s uncompress failed with error code %d\\n\", comp->name, error);\n\t\t\treturn 0;\n\t\t}\n\t} else {\n\t\tres = read_fs_bytes(fd, start + 2, c_byte, block);\n\t\tif (res == 0)\n\t\t\treturn 0;\n\t\tres = c_byte;\n\t}\n\n\tif (next)\n\t\t*next = start + 2 + c_byte;\n\n\t/*\n\t * if expected, then check the (uncompressed) return data\n\t * is of the expected size\n\t */\n\tif (expected && expected != res)\n\t\treturn 0;\n\telse\n\t\treturn res;\n}\n\n#define NO_BYTES(SIZE) \\\n\t(bytes - (cur_ptr - *inode_table) < (SIZE))\n\n#define NO_INODE_BYTES(INODE) NO_BYTES(sizeof(struct INODE))\n\nint 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\n\t\t\t\t\t *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) {\n\tunsigned char *cur_ptr;\n\tint byte, files = 0;\n\tunsigned int directory_start_block, bytes = 0, size = 0;\n\tstruct squashfs_base_inode_header base;\n\n\tTRACE(\"scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start \" \"0x%llx\\n\", start, end, root_inode_start);\n\n\t*root_inode_block = UINT_MAX;\n\twhile (start < end) {\n\t\tif (start == root_inode_start) {\n\t\t\tTRACE(\"scan_inode_table: read compressed block 0x%llx \" \"containing root inode\\n\", start);\n\t\t\t*root_inode_block = bytes;\n\t\t}\n\t\tif (size - bytes < SQUASHFS_METADATA_SIZE) {\n\t\t\t*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE);\n\t\t\tif (*inode_table == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t}\n\t\tTRACE(\"scan_inode_table: reading block 0x%llx\\n\", start);\n\t\tbyte = read_block(fd, start, &start, 0, *inode_table + bytes);\n\t\tif (byte == 0)\n\t\t\tgoto corrupted;\n\n\t\tbytes += byte;\n\n\t\t/* If this is not the last metadata block in the inode table\n\t\t * then it should be SQUASHFS_METADATA_SIZE in size.\n\t\t * Note, we can't use expected in read_block() above for this\n\t\t * because we don't know if this is the last block until\n\t\t * after reading.\n\t\t */\n\t\tif (start != end && byte != SQUASHFS_METADATA_SIZE)\n\t\t\tgoto corrupted;\n\t}\n\n\t/*\n\t * We expect to have found the metadata block containing the\n\t * root inode in the above inode_table metadata block scan.  If it\n\t * hasn't been found then the filesystem is corrupted\n\t */\n\tif (*root_inode_block == UINT_MAX)\n\t\tgoto corrupted;\n\n\t/*\n\t * The number of bytes available after the root inode medata block\n\t * should be at least the root inode offset + the size of a\n\t * regular directory inode, if not the filesystem is corrupted\n\t *\n\t *  +-----------------------+-----------------------+\n\t *  |           |        directory  |\n\t *  |           |          inode    |\n\t *  +-----------------------+-----------------------+\n\t *  ^           ^           ^\n\t *  *root_inode_block   root_inode_offset   bytes\n\t */\n\tif ((bytes - *root_inode_block) < (root_inode_offset + sizeof(struct squashfs_dir_inode_header)))\n\t\tgoto corrupted;\n\n\t/*\n\t * Read last inode entry which is the root directory inode, and obtain\n\t * the last directory start block index.  This is used when calculating\n\t * the total uncompressed directory size.  The directory bytes in the\n\t * last * block will be counted as normal.\n\t *\n\t * Note, the previous check ensures the following calculation won't\n\t * underflow, and we won't access beyond the buffer\n\t */\n\t*root_inode_size = bytes - (*root_inode_block + root_inode_offset);\n\tbytes = *root_inode_block + root_inode_offset;\n\tSQUASHFS_SWAP_DIR_INODE_HEADER(*inode_table + bytes, &dir_inode->dir);\n\n\tif (dir_inode->base.inode_type == SQUASHFS_DIR_TYPE)\n\t\tdirectory_start_block = dir_inode->dir.start_block;\n\telse if (dir_inode->base.inode_type == SQUASHFS_LDIR_TYPE) {\n\t\tif (*root_inode_size < sizeof(struct squashfs_ldir_inode_header))\n\t\t\t/* corrupted filesystem */\n\t\t\tgoto corrupted;\n\t\tSQUASHFS_SWAP_LDIR_INODE_HEADER(*inode_table + bytes, &dir_inode->ldir);\n\t\tdirectory_start_block = dir_inode->ldir.start_block;\n\t} else\n\t\t/* bad type, corrupted filesystem */\n\t\tgoto corrupted;\n\n\tget_uid(id_table[dir_inode->base.uid]);\n\tget_guid(id_table[dir_inode->base.guid]);\n\n\t/* allocate fragment to file mapping table */\n\tfile_mapping = calloc(sBlk->fragments, sizeof(struct append_file *));\n\tif (file_mapping == NULL)\n\t\tMEM_ERROR();\n\n\tfor (cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files++) {\n\t\tif (NO_INODE_BYTES(squashfs_base_inode_header))\n\t\t\t/* corrupted filesystem */\n\t\t\tgoto corrupted;\n\n\t\tSQUASHFS_SWAP_BASE_INODE_HEADER(cur_ptr, &base);\n\n\t\tTRACE(\"scan_inode_table: processing inode @ byte position \" \"0x%x, type 0x%x\\n\", (unsigned int)(cur_ptr - *inode_table), base.inode_type);\n\n\t\tget_uid(id_table[base.uid]);\n\t\tget_guid(id_table[base.guid]);\n\n\t\tswitch (base.inode_type) {\n\t\tcase SQUASHFS_FILE_TYPE:{\n\t\t\t\tstruct squashfs_reg_inode_header inode;\n\t\t\t\tint frag_bytes, blocks, i;\n\t\t\t\tlong long start, file_bytes = 0;\n\t\t\t\tunsigned int *block_list;\n\n\t\t\t\tif (NO_INODE_BYTES(squashfs_reg_inode_header))\n\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\tgoto corrupted;\n\n\t\t\t\tSQUASHFS_SWAP_REG_INODE_HEADER(cur_ptr, &inode);\n\n\t\t\t\tfrag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size;\n\t\t\t\tblocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log;\n\t\t\t\tstart = inode.start_block;\n\n\t\t\t\tTRACE(\"scan_inode_table: regular file, file_size %d, \" \"blocks %d\\n\", inode.file_size, blocks);\n\n\t\t\t\tif (NO_BYTES(blocks * sizeof(unsigned int)))\n\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\tgoto corrupted;\n\n\t\t\t\tblock_list = malloc(blocks * sizeof(unsigned int));\n\t\t\t\tif (block_list == NULL)\n\t\t\t\t\tMEM_ERROR();\n\n\t\t\t\tcur_ptr += sizeof(inode);\n\t\t\t\tSQUASHFS_SWAP_INTS(cur_ptr, block_list, blocks);\n\n\t\t\t\t*uncompressed_file += inode.file_size;\n\t\t\t\t(*file_count)++;\n\n\t\t\t\tfor (i = 0; i < blocks; i++)\n\t\t\t\t\tfile_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]);\n\n\t\t\t\tif (inode.fragment != SQUASHFS_INVALID_FRAG && inode.fragment >= sBlk->fragments) {\n\t\t\t\t\tfree(block_list);\n\t\t\t\t\tgoto corrupted;\n\t\t\t\t}\n\n\t\t\t\tadd_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes);\n\n\t\t\t\tcur_ptr += blocks * sizeof(unsigned int);\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase SQUASHFS_LREG_TYPE:{\n\t\t\t\tstruct squashfs_lreg_inode_header inode;\n\t\t\t\tint frag_bytes, blocks, i;\n\t\t\t\tlong long start, file_bytes = 0;\n\t\t\t\tunsigned int *block_list;\n\n\t\t\t\tif (NO_INODE_BYTES(squashfs_lreg_inode_header))\n\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\tgoto corrupted;\n\n\t\t\t\tSQUASHFS_SWAP_LREG_INODE_HEADER(cur_ptr, &inode);\n\n\t\t\t\tfrag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size;\n\t\t\t\tblocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log;\n\t\t\t\tstart = inode.start_block;\n\n\t\t\t\tTRACE(\"scan_inode_table: extended regular \" \"file, file_size %lld, blocks %d\\n\", inode.file_size, blocks);\n\n\t\t\t\tif (NO_BYTES(blocks * sizeof(unsigned int)))\n\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\tgoto corrupted;\n\n\t\t\t\tblock_list = malloc(blocks * sizeof(unsigned int));\n\t\t\t\tif (block_list == NULL)\n\t\t\t\t\tMEM_ERROR();\n\n\t\t\t\tcur_ptr += sizeof(inode);\n\t\t\t\tSQUASHFS_SWAP_INTS(cur_ptr, block_list, blocks);\n\n\t\t\t\t*uncompressed_file += inode.file_size;\n\t\t\t\t(*file_count)++;\n\n\t\t\t\tfor (i = 0; i < blocks; i++)\n\t\t\t\t\tfile_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]);\n\n\t\t\t\tif (inode.fragment != SQUASHFS_INVALID_FRAG && inode.fragment >= sBlk->fragments) {\n\t\t\t\t\tfree(block_list);\n\t\t\t\t\tgoto corrupted;\n\t\t\t\t}\n\n\t\t\t\tadd_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes);\n\n\t\t\t\tcur_ptr += blocks * sizeof(unsigned int);\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase SQUASHFS_SYMLINK_TYPE:\n\t\tcase SQUASHFS_LSYMLINK_TYPE:{\n\t\t\t\tstruct squashfs_symlink_inode_header inode;\n\n\t\t\t\tif (NO_INODE_BYTES(squashfs_symlink_inode_header))\n\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\tgoto corrupted;\n\n\t\t\t\tSQUASHFS_SWAP_SYMLINK_INODE_HEADER(cur_ptr, &inode);\n\n\t\t\t\t(*sym_count)++;\n\n\t\t\t\tif (inode.inode_type == SQUASHFS_LSYMLINK_TYPE) {\n\t\t\t\t\tif (NO_BYTES(inode.symlink_size + sizeof(unsigned int)))\n\t\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\t\tgoto corrupted;\n\t\t\t\t\tcur_ptr += sizeof(inode) + inode.symlink_size + sizeof(unsigned int);\n\t\t\t\t} else {\n\t\t\t\t\tif (NO_BYTES(inode.symlink_size))\n\t\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\t\tgoto corrupted;\n\t\t\t\t\tcur_ptr += sizeof(inode) + inode.symlink_size;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase SQUASHFS_DIR_TYPE:{\n\t\t\t\tstruct squashfs_dir_inode_header dir_inode;\n\n\t\t\t\tif (NO_INODE_BYTES(squashfs_dir_inode_header))\n\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\tgoto corrupted;\n\n\t\t\t\tSQUASHFS_SWAP_DIR_INODE_HEADER(cur_ptr, &dir_inode);\n\n\t\t\t\tif (dir_inode.start_block < directory_start_block)\n\t\t\t\t\t*uncompressed_directory += dir_inode.file_size;\n\n\t\t\t\t(*dir_count)++;\n\t\t\t\tcur_ptr += sizeof(struct squashfs_dir_inode_header);\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase SQUASHFS_LDIR_TYPE:{\n\t\t\t\tstruct squashfs_ldir_inode_header dir_inode;\n\t\t\t\tint i;\n\n\t\t\t\tif (NO_INODE_BYTES(squashfs_ldir_inode_header))\n\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\tgoto corrupted;\n\n\t\t\t\tSQUASHFS_SWAP_LDIR_INODE_HEADER(cur_ptr, &dir_inode);\n\n\t\t\t\tif (dir_inode.start_block < directory_start_block)\n\t\t\t\t\t*uncompressed_directory += dir_inode.file_size;\n\n\t\t\t\t(*dir_count)++;\n\t\t\t\tcur_ptr += sizeof(struct squashfs_ldir_inode_header);\n\n\t\t\t\tfor (i = 0; i < dir_inode.i_count; i++) {\n\t\t\t\t\tstruct squashfs_dir_index index;\n\n\t\t\t\t\tif (NO_BYTES(sizeof(index)))\n\t\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\t\tgoto corrupted;\n\n\t\t\t\t\tSQUASHFS_SWAP_DIR_INDEX(cur_ptr, &index);\n\n\t\t\t\t\tif (NO_BYTES(index.size + 1))\n\t\t\t\t\t\t/* corrupted filesystem */\n\t\t\t\t\t\tgoto corrupted;\n\n\t\t\t\t\tcur_ptr += sizeof(index) + index.size + 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase SQUASHFS_BLKDEV_TYPE:\n\t\tcase SQUASHFS_CHRDEV_TYPE:\n\t\t\tif (NO_INODE_BYTES(squashfs_dev_inode_header))\n\t\t\t\t/* corrupted filesystem */\n\t\t\t\tgoto corrupted;\n\n\t\t\t(*dev_count)++;\n\t\t\tcur_ptr += sizeof(struct squashfs_dev_inode_header);\n\t\t\tbreak;\n\t\tcase SQUASHFS_LBLKDEV_TYPE:\n\t\tcase SQUASHFS_LCHRDEV_TYPE:\n\t\t\tif (NO_INODE_BYTES(squashfs_ldev_inode_header))\n\t\t\t\t/* corrupted filesystem */\n\t\t\t\tgoto corrupted;\n\n\t\t\t(*dev_count)++;\n\t\t\tcur_ptr += sizeof(struct squashfs_ldev_inode_header);\n\t\t\tbreak;\n\t\tcase SQUASHFS_FIFO_TYPE:\n\t\t\tif (NO_INODE_BYTES(squashfs_ipc_inode_header))\n\t\t\t\t/* corrupted filesystem */\n\t\t\t\tgoto corrupted;\n\n\t\t\t(*fifo_count)++;\n\t\t\tcur_ptr += sizeof(struct squashfs_ipc_inode_header);\n\t\t\tbreak;\n\t\tcase SQUASHFS_LFIFO_TYPE:\n\t\t\tif (NO_INODE_BYTES(squashfs_lipc_inode_header))\n\t\t\t\t/* corrupted filesystem */\n\t\t\t\tgoto corrupted;\n\n\t\t\t(*fifo_count)++;\n\t\t\tcur_ptr += sizeof(struct squashfs_lipc_inode_header);\n\t\t\tbreak;\n\t\tcase SQUASHFS_SOCKET_TYPE:\n\t\t\tif (NO_INODE_BYTES(squashfs_ipc_inode_header))\n\t\t\t\t/* corrupted filesystem */\n\t\t\t\tgoto corrupted;\n\n\t\t\t(*sock_count)++;\n\t\t\tcur_ptr += sizeof(struct squashfs_ipc_inode_header);\n\t\t\tbreak;\n\t\tcase SQUASHFS_LSOCKET_TYPE:\n\t\t\tif (NO_INODE_BYTES(squashfs_lipc_inode_header))\n\t\t\t\t/* corrupted filesystem */\n\t\t\t\tgoto corrupted;\n\n\t\t\t(*sock_count)++;\n\t\t\tcur_ptr += sizeof(struct squashfs_lipc_inode_header);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tERROR(\"Unknown inode type %d in scan_inode_table!\\n\", base.inode_type);\n\t\t\tgoto corrupted;\n\t\t}\n\t}\n\n\tprintf(\"Read existing filesystem, %d inodes scanned\\n\", files);\n\treturn TRUE;\n\n corrupted:\n\tERROR(\"scan_inode_table: filesystem corruption detected in \" \"scanning metadata\\n\");\n\tfree(*inode_table);\n\treturn FALSE;\n}\n\nstruct compressor *read_super(int fd, struct squashfs_super_block *sBlk, char *source) {\n\tint res, bytes = 0;\n\tchar buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned));\n\n\tres = read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), sBlk);\n\tif (res == 0) {\n\t\tERROR(\"Can't find a SQUASHFS superblock on %s\\n\", source);\n\t\tERROR(\"Wrong filesystem or filesystem is corrupted!\\n\");\n\t\tgoto failed_mount;\n\t}\n\n\tSQUASHFS_INSWAP_SUPER_BLOCK(sBlk);\n\n\tif (sBlk->s_magic != SQUASHFS_MAGIC) {\n\t\tif (sBlk->s_magic == SQUASHFS_MAGIC_SWAP)\n\t\t\tERROR(\"Pre 4.0 big-endian filesystem on %s, appending\" \" to this is unsupported\\n\", source);\n\t\telse {\n\t\t\tERROR(\"Can't find a SQUASHFS superblock on %s\\n\", source);\n\t\t\tERROR(\"Wrong filesystem or filesystem is corrupted!\\n\");\n\t\t}\n\t\tgoto failed_mount;\n\t}\n\n\t/* Check the MAJOR & MINOR versions */\n\tif (sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) {\n\t\tif (sBlk->s_major < 4)\n\t\t\tERROR(\"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);\n\t\telse\n\t\t\tERROR(\"Filesystem on %s is %d.%d, which is a later \" \"filesystem version than I support\\n\", source, sBlk->s_major, sBlk->s_minor);\n\t\tgoto failed_mount;\n\t}\n\n\t/* Check the compression type */\n\tcomp = lookup_compressor_id(sBlk->compression);\n\tif (!comp->supported) {\n\t\tERROR(\"Filesystem on %s uses %s compression, this is \" \"unsupported by this version\\n\", source, comp->name);\n\t\tERROR(\"Compressors available:\\n\");\n\t\tdisplay_compressors(\"\", \"\");\n\t\tgoto failed_mount;\n\t}\n\n\t/*\n\t * Read extended superblock information from disk.\n\t *\n\t * Read compressor specific options from disk if present, and pass\n\t * to compressor to set compressor options.\n\t *\n\t * Note, if there's no compressor options present, the compressor\n\t * is still called to set the default options (the defaults may have\n\t * been changed by the user specifying options on the command\n\t * line which need to be over-ridden).\n\t *\n\t * Compressor_extract_options is also used to ensure that\n\t * we know how decompress a filesystem compressed with these\n\t * compression options.\n\t */\n\tif (SQUASHFS_COMP_OPTS(sBlk->flags)) {\n\t\tbytes = read_block(fd, sizeof(*sBlk), NULL, 0, buffer);\n\n\t\tif (bytes == 0) {\n\t\t\tERROR(\"Failed to read compressor options from append \" \"filesystem\\n\");\n\t\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\t\tgoto failed_mount;\n\t\t}\n\t}\n\n\tres = compressor_extract_options(comp, sBlk->block_size, buffer, bytes);\n\tif (res == -1) {\n\t\tERROR(\"Compressor failed to set compressor options\\n\");\n\t\tgoto failed_mount;\n\t}\n\n\tprintf(\"Found a valid %sSQUASHFS superblock on %s.\\n\", SQUASHFS_EXPORTABLE(sBlk->flags) ? \"exportable \" : \"\", source);\n\tprintf(\"\\tCompression used %s\\n\", comp->name);\n\tprintf(\"\\tInodes are %scompressed\\n\", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? \"un\" : \"\");\n\tprintf(\"\\tData is %scompressed\\n\", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? \"un\" : \"\");\n\tprintf(\"\\tFragments are %scompressed\\n\", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? \"un\" : \"\");\n\tprintf(\"\\tXattrs are %scompressed\\n\", SQUASHFS_UNCOMPRESSED_XATTRS(sBlk->flags) ? \"un\" : \"\");\n\tprintf(\"\\tFragments are %spresent in the filesystem\\n\", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? \"not \" : \"\");\n\tprintf(\"\\tAlways-use-fragments option is %sspecified\\n\", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? \"\" : \"not \");\n\tprintf(\"\\tDuplicates are %sremoved\\n\", SQUASHFS_DUPLICATES(sBlk->flags) ? \"\" : \"not \");\n\tprintf(\"\\tXattrs are %sstored\\n\", SQUASHFS_NO_XATTRS(sBlk->flags) ? \"not \" : \"\");\n\tprintf(\"\\tFilesystem size %.2f Kbytes (%.2f Mbytes)\\n\", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0));\n\tprintf(\"\\tBlock size %d\\n\", sBlk->block_size);\n\tprintf(\"\\tNumber of fragments %d\\n\", sBlk->fragments);\n\tprintf(\"\\tNumber of inodes %d\\n\", sBlk->inodes);\n\tprintf(\"\\tNumber of ids %d\\n\", sBlk->no_ids);\n\tTRACE(\"sBlk->inode_table_start %llx\\n\", sBlk->inode_table_start);\n\tTRACE(\"sBlk->directory_table_start %llx\\n\", sBlk->directory_table_start);\n\tTRACE(\"sBlk->id_table_start %llx\\n\", sBlk->id_table_start);\n\tTRACE(\"sBlk->fragment_table_start %llx\\n\", sBlk->fragment_table_start);\n\tTRACE(\"sBlk->lookup_table_start %llx\\n\", sBlk->lookup_table_start);\n\tTRACE(\"sBlk->xattr_id_table_start %llx\\n\", sBlk->xattr_id_table_start);\n\tprintf(\"\\n\");\n\n\treturn comp;\n\n failed_mount:\n\treturn NULL;\n}\n\nunsigned 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)) {\n\tstruct squashfs_dir_header dirh;\n\tchar buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]\n\t\t__attribute__ ((aligned));\n\tstruct squashfs_dir_entry *dire = (struct squashfs_dir_entry *)buffer;\n\tunsigned char *directory_table = NULL;\n\tint byte, bytes = 0, dir_count;\n\tlong long start = sBlk->directory_table_start + directory_start_block, last_start_block = start;\n\n\tsize += offset;\n\tdirectory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1));\n\tif (directory_table == NULL)\n\t\tMEM_ERROR();\n\n\twhile (bytes < size) {\n\t\tint expected = (size - bytes) >= SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : 0;\n\n\t\tTRACE(\"squashfs_readdir: reading block 0x%llx, bytes read so \" \"far %d\\n\", start, bytes);\n\n\t\tlast_start_block = start;\n\t\tbyte = read_block(fd, start, &start, expected, directory_table + bytes);\n\t\tif (byte == 0) {\n\t\t\tERROR(\"Failed to read directory\\n\");\n\t\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\t\tfree(directory_table);\n\t\t\treturn NULL;\n\t\t}\n\t\tbytes += byte;\n\t}\n\n\tif (!root_entries)\n\t\tgoto all_done;\n\n\tbytes = offset;\n\twhile (bytes < size) {\n\t\tSQUASHFS_SWAP_DIR_HEADER(directory_table + bytes, &dirh);\n\n\t\tdir_count = dirh.count + 1;\n\t\tTRACE(\"squashfs_readdir: Read directory header @ byte position \" \"0x%x, 0x%x directory entries\\n\", bytes, dir_count);\n\t\tbytes += sizeof(dirh);\n\n\t\twhile (dir_count--) {\n\t\t\tSQUASHFS_SWAP_DIR_ENTRY(directory_table + bytes, dire);\n\t\t\tbytes += sizeof(*dire);\n\n\t\t\tmemcpy(dire->name, directory_table + bytes, dire->size + 1);\n\t\t\tdire->name[dire->size + 1] = '\\0';\n\t\t\tTRACE(\"squashfs_readdir: pushing directory entry %s, \" \"inode %x:%x, type 0x%x\\n\", dire->name, dirh.start_block, dire->offset, dire->type);\n\t\t\tpush_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type);\n\t\t\tbytes += dire->size + 1;\n\t\t}\n\t}\n\n all_done:\n\t*last_directory_block = (unsigned int)last_start_block - sBlk->directory_table_start;\n\treturn directory_table;\n}\n\nunsigned int *read_id_table(int fd, struct squashfs_super_block *sBlk) {\n\tint indexes = SQUASHFS_ID_BLOCKS(sBlk->no_ids);\n\tlong long index[indexes];\n\tint bytes = SQUASHFS_ID_BYTES(sBlk->no_ids);\n\tunsigned int *id_table;\n\tint res, i;\n\n\tid_table = malloc(bytes);\n\tif (id_table == NULL)\n\t\tMEM_ERROR();\n\n\tres = read_fs_bytes(fd, sBlk->id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk->no_ids), index);\n\tif (res == 0) {\n\t\tERROR(\"Failed to read id table index\\n\");\n\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\tfree(id_table);\n\t\treturn NULL;\n\t}\n\n\tSQUASHFS_INSWAP_ID_BLOCKS(index, indexes);\n\n\tfor (i = 0; i < indexes; i++) {\n\t\tint expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : bytes & (SQUASHFS_METADATA_SIZE - 1);\n\t\tint length = read_block(fd, index[i], NULL, expected,\n\t\t\t\t\t\t\t\t((unsigned char *)id_table) + (i * SQUASHFS_METADATA_SIZE));\n\t\tTRACE(\"Read id table block %d, from 0x%llx, length %d\\n\", i, index[i], length);\n\t\tif (length == 0) {\n\t\t\tERROR(\"Failed to read id table block %d, from 0x%llx, \" \"length %d\\n\", i, index[i], length);\n\t\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\t\tfree(id_table);\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\tSQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids);\n\n\tfor (i = 0; i < sBlk->no_ids; i++) {\n\t\tTRACE(\"Adding id %d to id tables\\n\", id_table[i]);\n\t\tcreate_id(id_table[i]);\n\t}\n\n\treturn id_table;\n}\n\nint read_fragment_table(int fd, struct squashfs_super_block *sBlk, struct squashfs_fragment_entry **fragment_table) {\n\tint res, i;\n\tint bytes = SQUASHFS_FRAGMENT_BYTES(sBlk->fragments);\n\tint indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments);\n\tlong long fragment_table_index[indexes];\n\n\tTRACE(\"read_fragment_table: %d fragments, reading %d fragment indexes \" \"from 0x%llx\\n\", sBlk->fragments, indexes, sBlk->fragment_table_start);\n\n\tif (sBlk->fragments == 0)\n\t\treturn 1;\n\n\t*fragment_table = malloc(bytes);\n\tif (*fragment_table == NULL)\n\t\tMEM_ERROR();\n\n\tres = read_fs_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), fragment_table_index);\n\tif (res == 0) {\n\t\tERROR(\"Failed to read fragment table index\\n\");\n\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\tfree(*fragment_table);\n\t\treturn 0;\n\t}\n\n\tSQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes);\n\n\tfor (i = 0; i < indexes; i++) {\n\t\tint expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : bytes & (SQUASHFS_METADATA_SIZE - 1);\n\t\tint length = read_block(fd, fragment_table_index[i], NULL,\n\t\t\t\t\t\t\t\texpected, ((unsigned char *)*fragment_table) + (i * SQUASHFS_METADATA_SIZE));\n\t\tTRACE(\"Read fragment table block %d, from 0x%llx, length %d\\n\", i, fragment_table_index[i], length);\n\t\tif (length == 0) {\n\t\t\tERROR(\"Failed to read fragment table block %d, from \" \"0x%llx, length %d\\n\", i, fragment_table_index[i], length);\n\t\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\t\tfree(*fragment_table);\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tfor (i = 0; i < sBlk->fragments; i++)\n\t\tSQUASHFS_INSWAP_FRAGMENT_ENTRY(&(*fragment_table)[i]);\n\n\treturn 1;\n}\n\nint read_inode_lookup_table(int fd, struct squashfs_super_block *sBlk, squashfs_inode ** inode_lookup_table) {\n\tint lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes);\n\tint indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes);\n\tlong long index[indexes];\n\tint res, i;\n\n\tif (sBlk->lookup_table_start == SQUASHFS_INVALID_BLK)\n\t\treturn 1;\n\n\t*inode_lookup_table = malloc(lookup_bytes);\n\tif (*inode_lookup_table == NULL)\n\t\tMEM_ERROR();\n\n\tres = read_fs_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), index);\n\tif (res == 0) {\n\t\tERROR(\"Failed to read inode lookup table index\\n\");\n\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\tfree(*inode_lookup_table);\n\t\treturn 0;\n\t}\n\n\tSQUASHFS_INSWAP_LONG_LONGS(index, indexes);\n\n\tfor (i = 0; i < indexes; i++) {\n\t\tint expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : lookup_bytes & (SQUASHFS_METADATA_SIZE - 1);\n\t\tint length = read_block(fd, index[i], NULL, expected,\n\t\t\t\t\t\t\t\t((unsigned char *)*inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE));\n\t\tTRACE(\"Read inode lookup table block %d, from 0x%llx, length \" \"%d\\n\", i, index[i], length);\n\t\tif (length == 0) {\n\t\t\tERROR(\"Failed to read inode lookup table block %d, \" \"from 0x%llx, length %d\\n\", i, index[i], length);\n\t\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\t\tfree(*inode_lookup_table);\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tSQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes);\n\n\treturn 1;\n}\n\nlong 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) {\n\tunsigned char *inode_table = NULL, *directory_table = NULL;\n\tlong long start = sBlk->inode_table_start;\n\tlong long end = sBlk->directory_table_start;\n\tlong long root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode);\n\tunsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode);\n\tunsigned int root_inode_block;\n\tunion squashfs_inode_header inode;\n\tunsigned int *id_table = NULL;\n\tint res;\n\n\tprintf(\"Scanning existing filesystem...\\n\");\n\n\tif (get_xattrs(fd, sBlk) == 0)\n\t\tgoto error;\n\n\tif (read_fragment_table(fd, sBlk, fragment_table) == 0)\n\t\tgoto error;\n\n\tif (read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0)\n\t\tgoto error;\n\n\tid_table = read_id_table(fd, sBlk);\n\tif (id_table == NULL)\n\t\tgoto error;\n\n\tres = 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);\n\tif (res == 0)\n\t\tgoto error;\n\n\t*uncompressed_inode = root_inode_block;\n\n\tif (inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) {\n\t\tif (inode.base.inode_type == SQUASHFS_DIR_TYPE) {\n\t\t\t*inode_dir_start_block = inode.dir.start_block;\n\t\t\t*inode_dir_offset = inode.dir.offset;\n\t\t\t*inode_dir_file_size = inode.dir.file_size - 3;\n\t\t\t*inode_dir_inode_number = inode.dir.inode_number;\n\t\t\t*inode_dir_parent_inode = inode.dir.parent_inode;\n\t\t} else {\n\t\t\t*inode_dir_start_block = inode.ldir.start_block;\n\t\t\t*inode_dir_offset = inode.ldir.offset;\n\t\t\t*inode_dir_file_size = inode.ldir.file_size - 3;\n\t\t\t*inode_dir_inode_number = inode.ldir.inode_number;\n\t\t\t*inode_dir_parent_inode = inode.ldir.parent_inode;\n\t\t}\n\n\t\tdirectory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry);\n\t\tif (directory_table == NULL)\n\t\t\tgoto error;\n\n\t\troot_inode_start -= start;\n\t\t*cinode_table = malloc(root_inode_start);\n\t\tif (*cinode_table == NULL)\n\t\t\tMEM_ERROR();\n\n\t\tres = read_fs_bytes(fd, start, root_inode_start, *cinode_table);\n\t\tif (res == 0) {\n\t\t\tERROR(\"Failed to read inode table\\n\");\n\t\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\t\tgoto error;\n\t\t}\n\n\t\t*cdirectory_table = malloc(*last_directory_block);\n\t\tif (*cdirectory_table == NULL)\n\t\t\tMEM_ERROR();\n\n\t\tres = read_fs_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table);\n\t\tif (res == 0) {\n\t\t\tERROR(\"Failed to read directory table\\n\");\n\t\t\tERROR(\"Filesystem corrupted?\\n\");\n\t\t\tgoto error;\n\t\t}\n\n\t\t*data_cache = malloc(root_inode_offset + *root_inode_size);\n\t\tif (*data_cache == NULL)\n\t\t\tMEM_ERROR();\n\n\t\tmemcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size);\n\n\t\t*directory_data_cache = malloc(*inode_dir_offset + *inode_dir_file_size);\n\t\tif (*directory_data_cache == NULL)\n\t\t\tMEM_ERROR();\n\n\t\tmemcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size);\n\n\t\tfree(id_table);\n\t\tfree(inode_table);\n\t\tfree(directory_table);\n\t\treturn sBlk->inode_table_start;\n\t}\n\n error:\n\tfree(id_table);\n\tfree(inode_table);\n\tfree(directory_table);\n\treturn 0;\n}\n"
  },
  {
    "path": "src/squashfs/read_xattrs.c",
    "content": "/*\n * Read a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2010, 2012, 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * read_xattrs.c\n */\n\n/*\n * Common xattr read code shared between mksquashfs and unsquashfs\n */\n\n#define TRUE 1\n#define FALSE 0\n#include <stdio.h>\n#include <string.h>\n\n#if !defined(linux) && !defined(__CYGWIN__)\n#    define __BYTE_ORDER BYTE_ORDER\n#    define __BIG_ENDIAN BIG_ENDIAN\n#    define __LITTLE_ENDIAN LITTLE_ENDIAN\n#else\n#    include <endian.h>\n#endif\n\n#include \"squashfs_fs.h\"\n#include \"squashfs_swap.h\"\n#include \"xattr.h\"\n#include \"error.h\"\n\n#include <stdlib.h>\n\nextern int read_fs_bytes(int, long long, int, void *);\nextern int read_block(int, long long, long long *, int, void *);\n\nstatic struct hash_entry {\n\tlong long start;\n\tunsigned int offset;\n\tstruct hash_entry *next;\n} *hash_table[65536];\n\nstatic struct squashfs_xattr_id *xattr_ids;\nstatic void *xattrs = NULL;\nstatic long long xattr_table_start;\n\n/*\n * Prefix lookup table, storing mapping to/from prefix string and prefix id\n */\nstruct prefix prefix_table[] = {\n\t{\"user.\", SQUASHFS_XATTR_USER},\n\t{\"trusted.\", SQUASHFS_XATTR_TRUSTED},\n\t{\"security.\", SQUASHFS_XATTR_SECURITY},\n\t{\"\", -1}\n};\n\n/*\n * store mapping from location of compressed block in fs ->\n * location of uncompressed block in memory\n */\nstatic void save_xattr_block(long long start, int offset) {\n\tstruct hash_entry *hash_entry = malloc(sizeof(*hash_entry));\n\tint hash = start & 0xffff;\n\n\tTRACE(\"save_xattr_block: start %lld, offset %d\\n\", start, offset);\n\n\tif (hash_entry == NULL)\n\t\tMEM_ERROR();\n\n\thash_entry->start = start;\n\thash_entry->offset = offset;\n\thash_entry->next = hash_table[hash];\n\thash_table[hash] = hash_entry;\n}\n\n/*\n * map from location of compressed block in fs ->\n * location of uncompressed block in memory\n */\nstatic int get_xattr_block(long long start) {\n\tint hash = start & 0xffff;\n\tstruct hash_entry *hash_entry = hash_table[hash];\n\n\tfor (; hash_entry; hash_entry = hash_entry->next)\n\t\tif (hash_entry->start == start)\n\t\t\tbreak;\n\n\tTRACE(\"get_xattr_block: start %lld, offset %d\\n\", start, hash_entry ? hash_entry->offset : -1);\n\n\treturn hash_entry ? hash_entry->offset : -1;\n}\n\n/*\n * construct the xattr_list entry from the fs xattr, including\n * mapping name and prefix into a full name\n */\nstatic int read_xattr_entry(struct xattr_list *xattr, struct squashfs_xattr_entry *entry, void *name) {\n\tint i, len, type = entry->type & XATTR_PREFIX_MASK;\n\n\tfor (i = 0; prefix_table[i].type != -1; i++)\n\t\tif (prefix_table[i].type == type)\n\t\t\tbreak;\n\n\tif (prefix_table[i].type == -1) {\n\t\tERROR(\"Unrecognised type in read_xattr_entry\\n\");\n\t\treturn 0;\n\t}\n\n\tlen = strlen(prefix_table[i].prefix);\n\txattr->full_name = malloc(len + entry->size + 1);\n\tif (xattr->full_name == NULL)\n\t\tMEM_ERROR();\n\n\tmemcpy(xattr->full_name, prefix_table[i].prefix, len);\n\tmemcpy(xattr->full_name + len, name, entry->size);\n\txattr->full_name[len + entry->size] = '\\0';\n\txattr->name = xattr->full_name + len;\n\txattr->size = entry->size;\n\txattr->type = type;\n\n\treturn 1;\n}\n\n/*\n * Read and decompress the xattr id table and the xattr metadata.\n * This is cached in memory for later use by get_xattr()\n */\nint read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk) {\n\tint res, bytes, i, indexes, index_bytes, ids;\n\tlong long *index, start, end;\n\tstruct squashfs_xattr_table id_table;\n\n\tTRACE(\"read_xattrs_from_disk\\n\");\n\n\tif (sBlk->xattr_id_table_start == SQUASHFS_INVALID_BLK)\n\t\treturn SQUASHFS_INVALID_BLK;\n\n\t/*\n\t * Read xattr id table, containing start of xattr metadata and the\n\t * number of xattrs in the file system\n\t */\n\tres = read_fs_bytes(fd, sBlk->xattr_id_table_start, sizeof(id_table), &id_table);\n\tif (res == 0)\n\t\treturn 0;\n\n\tSQUASHFS_INSWAP_XATTR_TABLE(&id_table);\n\n\t/*\n\t * Allocate and read the index to the xattr id table metadata\n\t * blocks\n\t */\n\tids = id_table.xattr_ids;\n\txattr_table_start = id_table.xattr_table_start;\n\tindex_bytes = SQUASHFS_XATTR_BLOCK_BYTES(ids);\n\tindexes = SQUASHFS_XATTR_BLOCKS(ids);\n\tindex = malloc(index_bytes);\n\tif (index == NULL)\n\t\tMEM_ERROR();\n\n\tres = read_fs_bytes(fd, sBlk->xattr_id_table_start + sizeof(id_table), index_bytes, index);\n\tif (res == 0)\n\t\tgoto failed1;\n\n\tSQUASHFS_INSWAP_LONG_LONGS(index, indexes);\n\n\t/*\n\t * Allocate enough space for the uncompressed xattr id table, and\n\t * read and decompress it\n\t */\n\tbytes = SQUASHFS_XATTR_BYTES(ids);\n\txattr_ids = malloc(bytes);\n\tif (xattr_ids == NULL)\n\t\tMEM_ERROR();\n\n\tfor (i = 0; i < indexes; i++) {\n\t\tint expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : bytes & (SQUASHFS_METADATA_SIZE - 1);\n\t\tint length = read_block(fd, index[i], NULL, expected,\n\t\t\t\t\t\t\t\t((unsigned char *)xattr_ids) + (i * SQUASHFS_METADATA_SIZE));\n\t\tTRACE(\"Read xattr id table block %d, from 0x%llx, length \" \"%d\\n\", i, index[i], length);\n\t\tif (length == 0) {\n\t\t\tERROR(\"Failed to read xattr id table block %d, \" \"from 0x%llx, length %d\\n\", i, index[i], length);\n\t\t\tgoto failed2;\n\t\t}\n\t}\n\n\t/*\n\t * Read and decompress the xattr metadata\n\t *\n\t * Note the first xattr id table metadata block is immediately after\n\t * the last xattr metadata block, so we can use index[0] to work out\n\t * the end of the xattr metadata\n\t */\n\tstart = xattr_table_start;\n\tend = index[0];\n\tfor (i = 0; start < end; i++) {\n\t\tint length;\n\t\txattrs = realloc(xattrs, (i + 1) * SQUASHFS_METADATA_SIZE);\n\t\tif (xattrs == NULL)\n\t\t\tMEM_ERROR();\n\n\t\t/* store mapping from location of compressed block in fs ->\n\t\t * location of uncompressed block in memory */\n\t\tsave_xattr_block(start, i * SQUASHFS_METADATA_SIZE);\n\n\t\tlength = read_block(fd, start, &start, 0, ((unsigned char *)xattrs) + (i * SQUASHFS_METADATA_SIZE));\n\t\tTRACE(\"Read xattr block %d, length %d\\n\", i, length);\n\t\tif (length == 0) {\n\t\t\tERROR(\"Failed to read xattr block %d\\n\", i);\n\t\t\tgoto failed3;\n\t\t}\n\n\t\t/*\n\t\t * If this is not the last metadata block in the xattr metadata\n\t\t * then it should be SQUASHFS_METADATA_SIZE in size.\n\t\t * Note, we can't use expected in read_block() above for this\n\t\t * because we don't know if this is the last block until\n\t\t * after reading.\n\t\t */\n\t\tif (start != end && length != SQUASHFS_METADATA_SIZE) {\n\t\t\tERROR(\"Xattr block %d should be %d bytes in length, \" \"it is %d bytes\\n\", i, SQUASHFS_METADATA_SIZE, length);\n\t\t\tgoto failed3;\n\t\t}\n\t}\n\n\t/* swap if necessary the xattr id entries */\n\tfor (i = 0; i < ids; i++)\n\t\tSQUASHFS_INSWAP_XATTR_ID(&xattr_ids[i]);\n\n\tfree(index);\n\n\treturn ids;\n\n failed3:\n\tfree(xattrs);\n failed2:\n\tfree(xattr_ids);\n failed1:\n\tfree(index);\n\n\treturn 0;\n}\n\nvoid free_xattr(struct xattr_list *xattr_list, int count) {\n\tint i;\n\n\tfor (i = 0; i < count; i++)\n\t\tfree(xattr_list[i].full_name);\n\n\tfree(xattr_list);\n}\n\n/*\n * Construct and return the list of xattr name:value pairs for the passed xattr\n * id\n *\n * There are two users for get_xattr(), Mksquashfs uses it to read the\n * xattrs from the filesystem on appending, and Unsquashfs uses it\n * to retrieve the xattrs for writing to disk.\n *\n * Unfortunately, the two users disagree on what to do with unknown\n * xattr prefixes, Mksquashfs wants to treat this as fatal otherwise\n * this will cause xattrs to be be lost on appending.  Unsquashfs\n * on the otherhand wants to retrieve the xattrs which are known and\n * to ignore the rest, this allows Unsquashfs to cope more gracefully\n * with future versions which may have unknown xattrs, as long as the\n * general xattr structure is adhered to, Unsquashfs should be able\n * to safely ignore unknown xattrs, and to write the ones it knows about,\n * this is better than completely refusing to retrieve all the xattrs.\n *\n * If ignore is TRUE then don't treat unknown xattr prefixes as\n * a failure to read the xattr.\n */\nstruct xattr_list *get_xattr(int i, unsigned int *count, int ignore) {\n\tlong long start;\n\tstruct xattr_list *xattr_list = NULL;\n\tunsigned int offset;\n\tvoid *xptr;\n\tint j = 0, res = 1;\n\n\tTRACE(\"get_xattr\\n\");\n\n\t*count = xattr_ids[i].count;\n\tstart = SQUASHFS_XATTR_BLK(xattr_ids[i].xattr) + xattr_table_start;\n\toffset = SQUASHFS_XATTR_OFFSET(xattr_ids[i].xattr);\n\txptr = xattrs + get_xattr_block(start) + offset;\n\n\tTRACE(\"get_xattr: xattr_id %d, count %d, start %lld, offset %d\\n\", i, *count, start, offset);\n\n\twhile (j < *count) {\n\t\tstruct squashfs_xattr_entry entry;\n\t\tstruct squashfs_xattr_val val;\n\n\t\tif (res != 0) {\n\t\t\txattr_list = realloc(xattr_list, (j + 1) * sizeof(struct xattr_list));\n\t\t\tif (xattr_list == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t}\n\n\t\tSQUASHFS_SWAP_XATTR_ENTRY(xptr, &entry);\n\t\txptr += sizeof(entry);\n\n\t\tres = read_xattr_entry(&xattr_list[j], &entry, xptr);\n\t\tif (ignore && res == 0) {\n\t\t\t/* unknown prefix, but ignore flag is set */\n\t\t\t(*count)--;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (res != 1)\n\t\t\tgoto failed;\n\n\t\txptr += entry.size;\n\n\t\tTRACE(\"get_xattr: xattr %d, type %d, size %d, name %s\\n\", j, entry.type, entry.size, xattr_list[j].full_name);\n\n\t\tif (entry.type & SQUASHFS_XATTR_VALUE_OOL) {\n\t\t\tlong long xattr;\n\t\t\tvoid *ool_xptr;\n\n\t\t\txptr += sizeof(val);\n\t\t\tSQUASHFS_SWAP_LONG_LONGS(xptr, &xattr, 1);\n\t\t\txptr += sizeof(xattr);\n\t\t\tstart = SQUASHFS_XATTR_BLK(xattr) + xattr_table_start;\n\t\t\toffset = SQUASHFS_XATTR_OFFSET(xattr);\n\t\t\tool_xptr = xattrs + get_xattr_block(start) + offset;\n\t\t\tSQUASHFS_SWAP_XATTR_VAL(ool_xptr, &val);\n\t\t\txattr_list[j].value = ool_xptr + sizeof(val);\n\t\t} else {\n\t\t\tSQUASHFS_SWAP_XATTR_VAL(xptr, &val);\n\t\t\txattr_list[j].value = xptr + sizeof(val);\n\t\t\txptr += sizeof(val) + val.vsize;\n\t\t}\n\n\t\tTRACE(\"get_xattr: xattr %d, vsize %d\\n\", j, val.vsize);\n\n\t\txattr_list[j++].vsize = val.vsize;\n\t}\n\n\tif (*count == 0)\n\t\tgoto failed;\n\n\treturn xattr_list;\n\n failed:\n\tfree_xattr(xattr_list, j);\n\n\treturn NULL;\n}\n"
  },
  {
    "path": "src/squashfs/restore.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * restore.c\n */\n\n#include <pthread.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include <signal.h>\n#include <sys/time.h>\n#include <stdio.h>\n#include <math.h>\n#include <stdarg.h>\n#include <errno.h>\n#include <stdlib.h>\n#include <dirent.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#include \"caches-queues-lists.h\"\n#include \"squashfs_fs.h\"\n#include \"mksquashfs.h\"\n#include \"error.h\"\n#include \"progressbar.h\"\n#include \"info.h\"\n\n#define FALSE 0\n#define TRUE 1\n\nextern pthread_t reader_thread, writer_thread, main_thread;\nextern pthread_t *deflator_thread, *frag_deflator_thread, *frag_thread;\nextern struct queue *to_deflate, *to_writer, *to_frag, *to_process_frag;\nextern struct seq_queue *to_main;\nextern void restorefs();\nextern int processors;\n\nstatic int interrupted = 0;\nstatic pthread_t restore_thread;\n\nvoid *restore_thrd(void *arg) {\n\tsigset_t sigmask, old_mask;\n\tint i, sig;\n\n\tsigemptyset(&sigmask);\n\tsigaddset(&sigmask, SIGINT);\n\tsigaddset(&sigmask, SIGTERM);\n\tsigaddset(&sigmask, SIGUSR1);\n\tpthread_sigmask(SIG_BLOCK, &sigmask, &old_mask);\n\n\twhile (1) {\n\t\tsigwait(&sigmask, &sig);\n\n\t\tif ((sig == SIGINT || sig == SIGTERM) && !interrupted) {\n\t\t\tERROR(\"Interrupting will restore original \" \"filesystem!\\n\");\n\t\t\tERROR(\"Interrupt again to quit\\n\");\n\t\t\tinterrupted = TRUE;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* kill main thread/worker threads and restore */\n\t\tset_progressbar_state(FALSE);\n\t\tdisable_info();\n\n\t\t/* first kill the reader thread */\n\t\tpthread_cancel(reader_thread);\n\t\tpthread_join(reader_thread, NULL);\n\n\t\t/*\n\t\t * then flush the reader to deflator thread(s) output queue.\n\t\t * The deflator thread(s) will idle\n\t\t */\n\t\tqueue_flush(to_deflate);\n\n\t\t/* now kill the deflator thread(s) */\n\t\tfor (i = 0; i < processors; i++)\n\t\t\tpthread_cancel(deflator_thread[i]);\n\t\tfor (i = 0; i < processors; i++)\n\t\t\tpthread_join(deflator_thread[i], NULL);\n\n\t\t/*\n\t\t * then flush the reader to process fragment thread(s) output\n\t\t * queue.  The process fragment thread(s) will idle\n\t\t */\n\t\tqueue_flush(to_process_frag);\n\n\t\t/* now kill the process fragment thread(s) */\n\t\tfor (i = 0; i < processors; i++)\n\t\t\tpthread_cancel(frag_thread[i]);\n\t\tfor (i = 0; i < processors; i++)\n\t\t\tpthread_join(frag_thread[i], NULL);\n\n\t\t/*\n\t\t * then flush the reader/deflator/process fragment to main\n\t\t * thread output queue.  The main thread will idle\n\t\t */\n\t\tseq_queue_flush(to_main);\n\n\t\t/* now kill the main thread */\n\t\tpthread_cancel(main_thread);\n\t\tpthread_join(main_thread, NULL);\n\n\t\t/* then flush the main thread to fragment deflator thread(s)\n\t\t * queue.  The fragment deflator thread(s) will idle\n\t\t */\n\t\tqueue_flush(to_frag);\n\n\t\t/* now kill the fragment deflator thread(s) */\n\t\tfor (i = 0; i < processors; i++)\n\t\t\tpthread_cancel(frag_deflator_thread[i]);\n\t\tfor (i = 0; i < processors; i++)\n\t\t\tpthread_join(frag_deflator_thread[i], NULL);\n\n\t\t/*\n\t\t * then flush the main thread/fragment deflator thread(s)\n\t\t * to writer thread queue.  The writer thread will idle\n\t\t */\n\t\tqueue_flush(to_writer);\n\n\t\t/* now kill the writer thread */\n\t\tpthread_cancel(writer_thread);\n\t\tpthread_join(writer_thread, NULL);\n\n\t\tTRACE(\"All threads cancelled\\n\");\n\n\t\trestorefs();\n\t}\n}\n\npthread_t *init_restore_thread() {\n\tpthread_create(&restore_thread, NULL, restore_thrd, NULL);\n\treturn &restore_thread;\n}\n"
  },
  {
    "path": "src/squashfs/sort.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012,\n * 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * sort.c\n */\n\n#define TRUE 1\n#define FALSE 0\n#define MAX_LINE 16384\n\n#include <unistd.h>\n#include <stdio.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <dirent.h>\n#include <string.h>\n#include <stdlib.h>\n#include <ctype.h>\n\n#include \"squashfs_fs.h\"\n#include \"mksquashfs.h\"\n#include \"sort.h\"\n#include \"error.h\"\n#include \"progressbar.h\"\n\nint mkisofs_style = -1;\n\nstruct sort_info {\n\tdev_t st_dev;\n\tino_t st_ino;\n\tint priority;\n\tstruct sort_info *next;\n};\n\nstruct sort_info *sort_info_list[65536];\n\nstruct priority_entry *priority_list[65536];\n\nextern int silent;\nextern void write_file(squashfs_inode * inode, struct dir_ent *dir_ent, int *c_size);\nextern char *pathname(struct dir_ent *dir_ent);\n\nvoid add_priority_list(struct dir_ent *dir, int priority) {\n\tstruct priority_entry *new_priority_entry;\n\n\tpriority += 32768;\n\tnew_priority_entry = malloc(sizeof(struct priority_entry));\n\tif (new_priority_entry == NULL)\n\t\tMEM_ERROR();\n\n\tnew_priority_entry->dir = dir;;\n\tnew_priority_entry->next = priority_list[priority];\n\tpriority_list[priority] = new_priority_entry;\n}\n\nint get_priority(char *filename, struct stat *buf, int priority) {\n\tint hash = buf->st_ino & 0xffff;\n\tstruct sort_info *s;\n\n\tfor (s = sort_info_list[hash]; s; s = s->next)\n\t\tif ((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) {\n\t\t\tTRACE(\"returning priority %d (%s)\\n\", s->priority, filename);\n\t\t\treturn s->priority;\n\t\t}\n\tTRACE(\"returning priority %d (%s)\\n\", priority, filename);\n\treturn priority;\n}\n\n#define ADD_ENTRY(buf, priority) {\\\n\tint hash = buf.st_ino & 0xffff;\\\n\tstruct sort_info *s;\\\n\tif((s = malloc(sizeof(struct sort_info))) == NULL) \\\n\t\tMEM_ERROR(); \\\n\ts->st_dev = buf.st_dev;\\\n\ts->st_ino = buf.st_ino;\\\n\ts->priority = priority;\\\n\ts->next = sort_info_list[hash];\\\n\tsort_info_list[hash] = s;\\\n\t}\nint add_sort_list(char *path, int priority, int source, char *source_path[]) {\n\tint i, n;\n\tstruct stat buf;\n\n\tTRACE(\"add_sort_list: filename %s, priority %d\\n\", path, priority);\n\tif (strlen(path) > 1 && strcmp(path + strlen(path) - 2, \"/*\") == 0)\n\t\tpath[strlen(path) - 2] = '\\0';\n\n\tTRACE(\"add_sort_list: filename %s, priority %d\\n\", path, priority);\n re_read:\n\tif (path[0] == '/' || strncmp(path, \"./\", 2) == 0 || strncmp(path, \"../\", 3) == 0 || mkisofs_style == 1) {\n\t\tif (lstat(path, &buf) == -1)\n\t\t\tgoto error;\n\t\tTRACE(\"adding filename %s, priority %d, st_dev %d, st_ino \" \"%lld\\n\", path, priority, (int)buf.st_dev, (long long)buf.st_ino);\n\t\tADD_ENTRY(buf, priority);\n\t\treturn TRUE;\n\t}\n\n\tfor (i = 0, n = 0; i < source; i++) {\n\t\tchar *filename;\n\t\tint res = asprintf(&filename, \"%s/%s\", source_path[i], path);\n\t\tif (res == -1)\n\t\t\tBAD_ERROR(\"asprintf failed in add_sort_list\\n\");\n\t\tres = lstat(filename, &buf);\n\t\tfree(filename);\n\t\tif (res == -1) {\n\t\t\tif (!(errno == ENOENT || errno == ENOTDIR))\n\t\t\t\tgoto error;\n\t\t\tcontinue;\n\t\t}\n\t\tADD_ENTRY(buf, priority);\n\t\tn++;\n\t}\n\n\tif (n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) {\n\t\tERROR(\"WARNING: Mkisofs style sortlist detected! This is \" \"supported but please\\n\");\n\t\tERROR(\"convert to mksquashfs style sortlist! A sortlist entry\");\n\t\tERROR(\" should be\\neither absolute (starting with \");\n\t\tERROR(\"'/') start with './' or '../' (taken to be\\nrelative to \" \"$PWD), otherwise it \");\n\t\tERROR(\"is assumed the entry is relative to one\\nof the source \" \"directories, i.e. with \");\n\t\tERROR(\"\\\"mksquashfs test test.sqsh\\\",\\nthe sortlist \");\n\t\tERROR(\"entry \\\"file\\\" is assumed to be inside the directory \" \"test.\\n\\n\");\n\t\tmkisofs_style = 1;\n\t\tgoto re_read;\n\t}\n\n\tmkisofs_style = 0;\n\n\tif (n == 1)\n\t\treturn TRUE;\n\tif (n > 1) {\n\t\tERROR(\" Ambiguous sortlist entry \\\"%s\\\"\\n\\nIt maps to more \" \"than one source entry!  Please use an absolute path.\" \"\\n\", path);\n\t\treturn FALSE;\n\t}\n\n error:\n\tERROR_START(\"Cannot stat sortlist entry \\\"%s\\\"\\n\", path);\n\tERROR(\"This is probably because you're using the wrong file\\n\");\n\tERROR(\"path relative to the source directories.\");\n\tERROR_EXIT(\"  Ignoring\");\n\t/*\n\t * Historical note\n\t * Failure to stat a sortlist entry is deliberately ignored, even\n\t * though it is an error.  Squashfs release 2.2 changed the behaviour\n\t * to treat it as a fatal error, but it was changed back to\n\t * the original behaviour to ignore it in release 2.2-r2 following\n\t * feedback from users at the time.\n\t */\n\treturn TRUE;\n}\n\nvoid generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) {\n\tstruct dir_ent *dir_ent = dir->list;\n\n\tpriority = get_priority(dir->pathname, buf, priority);\n\n\tfor (; dir_ent; dir_ent = dir_ent->next) {\n\t\tstruct stat *buf = &dir_ent->inode->buf;\n\t\tif (dir_ent->inode->root_entry)\n\t\t\tcontinue;\n\n\t\tswitch (buf->st_mode & S_IFMT) {\n\t\tcase S_IFREG:\n\t\t\tadd_priority_list(dir_ent, get_priority(pathname(dir_ent), buf, priority));\n\t\t\tbreak;\n\t\tcase S_IFDIR:\n\t\t\tgenerate_file_priorities(dir_ent->dir, priority, buf);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nint read_sort_file(char *filename, int source, char *source_path[]) {\n\tFILE *fd;\n\tchar line_buffer[MAX_LINE + 1];\t/* overflow safe */\n\tchar sort_filename[MAX_LINE + 1];\t/* overflow safe */\n\tchar *line, *name;\n\tint n, priority, res;\n\n\tif ((fd = fopen(filename, \"r\")) == NULL) {\n\t\tERROR(\"Failed to open sort file \\\"%s\\\" because %s\\n\", filename, strerror(errno));\n\t\treturn FALSE;\n\t}\n\n\twhile (fgets(line = line_buffer, MAX_LINE + 1, fd) != NULL) {\n\t\tint len = strlen(line);\n\n\t\tif (len == MAX_LINE && line[len - 1] != '\\n') {\n\t\t\t/* line too large */\n\t\t\tERROR(\"Line too long when reading \" \"sort file \\\"%s\\\", larger than %d \" \"bytes\\n\", filename, MAX_LINE);\n\t\t\tgoto failed;\n\t\t}\n\n\t\t/*\n\t\t * Remove '\\n' terminator if it exists (the last line\n\t\t * in the file may not be '\\n' terminated)\n\t\t */\n\t\tif (len && line[len - 1] == '\\n')\n\t\t\tline[len - 1] = '\\0';\n\n\t\t/* Skip any leading whitespace */\n\t\twhile (isspace(*line))\n\t\t\tline++;\n\n\t\t/* if comment line, skip */\n\t\tif (*line == '#')\n\t\t\tcontinue;\n\n\t\t/*\n\t\t * Scan for filename, don't use sscanf() and \"%s\" because\n\t\t * that can't handle filenames with spaces\n\t\t */\n\t\tfor (name = sort_filename; !isspace(*line) && *line != '\\0';) {\n\t\t\tif (*line == '\\\\') {\n\t\t\t\tline++;\n\t\t\t\tif (*line == '\\0')\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t*name++ = *line++;\n\t\t}\n\t\t*name = '\\0';\n\n\t\t/*\n\t\t * if filename empty, then line was empty of anything but\n\t\t * whitespace or a backslash character.  Skip empy lines\n\t\t */\n\t\tif (sort_filename[0] == '\\0')\n\t\t\tcontinue;\n\n\t\t/*\n\t\t * Scan the rest of the line, we expect a decimal number\n\t\t * which is the filename priority\n\t\t */\n\t\terrno = 0;\n\t\tres = sscanf(line, \"%d%n\", &priority, &n);\n\n\t\tif ((res < 1 || errno) && errno != ERANGE) {\n\t\t\tif (errno == 0)\n\t\t\t\t/* No error, assume EOL or match failure */\n\t\t\t\tERROR(\"Sort file \\\"%s\\\", can't find priority \" \"in entry \\\"%s\\\", EOL or match \" \"failure\\n\", filename, line_buffer);\n\t\t\telse\n\t\t\t\t/* Some other failure not ERANGE */\n\t\t\t\tERROR(\"Sscanf failed reading sort file \\\"%s\\\" \" \"because %s\\n\", filename, strerror(errno));\n\t\t\tgoto failed;\n\t\t} else if ((errno == ERANGE) || (priority < -32768 || priority > 32767)) {\n\t\t\tERROR(\"Sort file \\\"%s\\\", entry \\\"%s\\\" has priority \" \"outside range of -32767:32768.\\n\", filename, line_buffer);\n\t\t\tgoto failed;\n\t\t}\n\n\t\t/* Skip any trailing whitespace */\n\t\tline += n;\n\t\twhile (isspace(*line))\n\t\t\tline++;\n\n\t\tif (*line != '\\0') {\n\t\t\tERROR(\"Sort file \\\"%s\\\", trailing characters after \" \"priority in entry \\\"%s\\\"\\n\", filename, line_buffer);\n\t\t\tgoto failed;\n\t\t}\n\n\t\tres = add_sort_list(sort_filename, priority, source, source_path);\n\t\tif (res == FALSE)\n\t\t\tgoto failed;\n\t}\n\n\tif (ferror(fd)) {\n\t\tERROR(\"Reading sort file \\\"%s\\\" failed because %s\\n\", filename, strerror(errno));\n\t\tgoto failed;\n\t}\n\n\tfclose(fd);\n\treturn TRUE;\n\n failed:\n\tfclose(fd);\n\treturn FALSE;\n}\n\nvoid sort_files_and_write(struct dir_info *dir) {\n\tint i;\n\tstruct priority_entry *entry;\n\tsquashfs_inode inode;\n\tint duplicate_file;\n\n\tfor (i = 65535; i >= 0; i--)\n\t\tfor (entry = priority_list[i]; entry; entry = entry->next) {\n\t\t\tTRACE(\"%d: %s\\n\", i - 32768, pathname(entry->dir));\n\t\t\tif (entry->dir->inode->inode == SQUASHFS_INVALID_BLK) {\n\t\t\t\twrite_file(&inode, entry->dir, &duplicate_file);\n\t\t\t\tINFO(\"file %s, uncompressed size %lld bytes %s\" \"\\n\", pathname(entry->dir), (long long)\n\t\t\t\t\t entry->dir->inode->buf.st_size, duplicate_file ? \"DUPLICATE\" : \"\");\n\t\t\t\tentry->dir->inode->inode = inode;\n\t\t\t\tentry->dir->inode->type = SQUASHFS_FILE_TYPE;\n\t\t\t} else\n\t\t\t\tINFO(\"file %s, uncompressed size %lld bytes \" \"LINK\\n\", pathname(entry->dir), (long long)\n\t\t\t\t\t entry->dir->inode->buf.st_size);\n\t\t}\n}\n"
  },
  {
    "path": "src/squashfs/swap.c",
    "content": "/*\n * Copyright (c) 2009, 2010\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * swap.c\n */\n\n#if !defined(linux) && !defined(__CYGWIN__)\n#    define __BYTE_ORDER BYTE_ORDER\n#    define __BIG_ENDIAN BIG_ENDIAN\n#    define __LITTLE_ENDIAN LITTLE_ENDIAN\n#else\n#    include <endian.h>\n#endif\n\n#if __BYTE_ORDER == __BIG_ENDIAN\nvoid swap_le16(void *src, void *dest) {\n\tunsigned char *s = src;\n\tunsigned char *d = dest;\n\n\td[0] = s[1];\n\td[1] = s[0];\n}\n\nvoid swap_le32(void *src, void *dest) {\n\tunsigned char *s = src;\n\tunsigned char *d = dest;\n\n\td[0] = s[3];\n\td[1] = s[2];\n\td[2] = s[1];\n\td[3] = s[0];\n}\n\nvoid swap_le64(void *src, void *dest) {\n\tunsigned char *s = src;\n\tunsigned char *d = dest;\n\n\td[0] = s[7];\n\td[1] = s[6];\n\td[2] = s[5];\n\td[3] = s[4];\n\td[4] = s[3];\n\td[5] = s[2];\n\td[6] = s[1];\n\td[7] = s[0];\n}\n\nunsigned short inswap_le16(unsigned short num) {\n\treturn (num >> 8) | ((num & 0xff) << 8);\n}\n\nunsigned int inswap_le32(unsigned int num) {\n\treturn (num >> 24) | ((num & 0xff0000) >> 8) | ((num & 0xff00) << 8) | ((num & 0xff) << 24);\n}\n\nlong long inswap_le64(long long n) {\n\tunsigned long long num = n;\n\n\treturn (num >> 56) | ((num & 0xff000000000000LL) >> 40) | ((num & 0xff0000000000LL) >> 24) | ((num & 0xff00000000LL) >> 8) | ((num & 0xff000000) << 8) | ((num & 0xff0000) << 24) | ((num & 0xff00) << 40) | ((num & 0xff) << 56);\n}\n\n#    define SWAP_LE_NUM(BITS) \\\nvoid swap_le##BITS##_num(void *s, void *d, int n) \\\n{\\\n\tint i;\\\n\tfor(i = 0; i < n; i++, s += BITS / 8, d += BITS / 8)\\\n\t\tswap_le##BITS(s, d);\\\n}\n\nSWAP_LE_NUM(16)\n\tSWAP_LE_NUM(32)\n\tSWAP_LE_NUM(64)\n#    define INSWAP_LE_NUM(BITS, TYPE) \\\nvoid inswap_le##BITS##_num(TYPE *s, int n) \\\n{\\\n\tint i;\\\n\tfor(i = 0; i < n; i++)\\\n\t\ts[i] = inswap_le##BITS(s[i]);\\\n}\n\tINSWAP_LE_NUM(16, unsigned short)\nINSWAP_LE_NUM(32, unsigned int) INSWAP_LE_NUM(64, long long)\n#endif\n"
  },
  {
    "path": "src/squashfs/unsquash-1.c",
    "content": "/*\n * Unsquash a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2009, 2010, 2011, 2012\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * unsquash-1.c\n */\n\n#include \"unsquashfs.h\"\n#include \"squashfs_compat.h\"\n\nvoid read_block_list_1(unsigned int *block_list, char *block_ptr, int blocks) {\n\tunsigned short block_size;\n\tint i;\n\n\tTRACE(\"read_block_list: blocks %d\\n\", blocks);\n\n\tfor (i = 0; i < blocks; i++, block_ptr += 2) {\n\t\tif (swap) {\n\t\t\tunsigned short sblock_size;\n\t\t\tmemcpy(&sblock_size, block_ptr, sizeof(unsigned short));\n\t\t\tSQUASHFS_SWAP_SHORTS_3((&block_size), &sblock_size, 1);\n\t\t} else\n\t\t\tmemcpy(&block_size, block_ptr, sizeof(unsigned short));\n\t\tblock_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK);\n\t}\n}\n\nint read_fragment_table_1(long long *directory_table_end) {\n\tTRACE(\"read_fragment_table\\n\");\n\t*directory_table_end = sBlk.s.fragment_table_start;\n\treturn TRUE;\n}\n\nstruct inode *read_inode_1(unsigned int start_block, unsigned int offset) {\n\tstatic union squashfs_inode_header_1 header;\n\tlong long start = sBlk.s.inode_table_start + start_block;\n\tint bytes = lookup_entry(inode_table_hash, start);\n\tchar *block_ptr = inode_table + bytes + offset;\n\tstatic struct inode i;\n\n\tTRACE(\"read_inode: reading inode [%d:%d]\\n\", start_block, offset);\n\n\tif (bytes == -1)\n\t\tEXIT_UNSQUASH(\"read_inode: inode table block %lld not found\\n\", start);\n\n\tif (swap) {\n\t\tsquashfs_base_inode_header_1 sinode;\n\t\tmemcpy(&sinode, block_ptr, sizeof(header.base));\n\t\tSQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1));\n\t} else\n\t\tmemcpy(&header.base, block_ptr, sizeof(header.base));\n\n\ti.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid];\n\tif (header.base.inode_type == SQUASHFS_IPC_TYPE) {\n\t\tsquashfs_ipc_inode_header_1 *inodep = &header.ipc;\n\n\t\tif (swap) {\n\t\t\tsquashfs_ipc_inode_header_1 sinodep;\n\t\t\tmemcpy(&sinodep, block_ptr, sizeof(sinodep));\n\t\t\tSQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep);\n\t\t} else\n\t\t\tmemcpy(inodep, block_ptr, sizeof(*inodep));\n\n\t\tif (inodep->type == SQUASHFS_SOCKET_TYPE) {\n\t\t\ti.mode = S_IFSOCK | header.base.mode;\n\t\t\ti.type = SQUASHFS_SOCKET_TYPE;\n\t\t} else {\n\t\t\ti.mode = S_IFIFO | header.base.mode;\n\t\t\ti.type = SQUASHFS_FIFO_TYPE;\n\t\t}\n\t\ti.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid];\n\t} else {\n\t\ti.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode;\n\t\ti.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1;\n\t}\n\n\ti.xattr = SQUASHFS_INVALID_XATTR;\n\ti.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid];\n\ti.time = sBlk.s.mkfs_time;\n\ti.inode_number = inode_number++;\n\n\tswitch (i.type) {\n\tcase SQUASHFS_DIR_TYPE:{\n\t\t\tsquashfs_dir_inode_header_1 *inode = &header.dir;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_dir_inode_header_1 sinode;\n\t\t\t\tmemcpy(&sinode, block_ptr, sizeof(header.dir));\n\t\t\t\tSQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode);\n\t\t\t} else\n\t\t\t\tmemcpy(inode, block_ptr, sizeof(header.dir));\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.time = inode->mtime;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_FILE_TYPE:{\n\t\t\tsquashfs_reg_inode_header_1 *inode = &header.reg;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_reg_inode_header_1 sinode;\n\t\t\t\tmemcpy(&sinode, block_ptr, sizeof(sinode));\n\t\t\t\tSQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode);\n\t\t\t} else\n\t\t\t\tmemcpy(inode, block_ptr, sizeof(*inode));\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.time = inode->mtime;\n\t\t\ti.blocks = (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.block_ptr = block_ptr + sizeof(*inode);\n\t\t\ti.fragment = 0;\n\t\t\ti.frag_bytes = 0;\n\t\t\ti.offset = 0;\n\t\t\ti.sparse = 0;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_SYMLINK_TYPE:{\n\t\t\tsquashfs_symlink_inode_header_1 *inodep = &header.symlink;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_symlink_inode_header_1 sinodep;\n\t\t\t\tmemcpy(&sinodep, block_ptr, sizeof(sinodep));\n\t\t\t\tSQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep);\n\t\t\t} else\n\t\t\t\tmemcpy(inodep, block_ptr, sizeof(*inodep));\n\n\t\t\ti.symlink = malloc(inodep->symlink_size + 1);\n\t\t\tif (i.symlink == NULL)\n\t\t\t\tEXIT_UNSQUASH(\"read_inode: failed to malloc \" \"symlink data\\n\");\n\t\t\tstrncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size);\n\t\t\ti.symlink[inodep->symlink_size] = '\\0';\n\t\t\ti.data = inodep->symlink_size;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_BLKDEV_TYPE:\n\tcase SQUASHFS_CHRDEV_TYPE:{\n\t\t\tsquashfs_dev_inode_header_1 *inodep = &header.dev;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_dev_inode_header_1 sinodep;\n\t\t\t\tmemcpy(&sinodep, block_ptr, sizeof(sinodep));\n\t\t\t\tSQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep);\n\t\t\t} else\n\t\t\t\tmemcpy(inodep, block_ptr, sizeof(*inodep));\n\n\t\t\ti.data = inodep->rdev;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_FIFO_TYPE:\n\tcase SQUASHFS_SOCKET_TYPE:{\n\t\t\ti.data = 0;\n\t\t\tbreak;\n\t\t}\n\tdefault:\n\t\tEXIT_UNSQUASH(\"Unknown inode type %d in \" \" read_inode_header_1!\\n\", header.base.inode_type);\n\t}\n\treturn &i;\n}\n\nstruct dir *squashfs_opendir_1(unsigned int block_start, unsigned int offset, struct inode **i) {\n\tsquashfs_dir_header_2 dirh;\n\tchar buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]\n\t\t__attribute__ ((aligned));\n\tsquashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer;\n\tlong long start;\n\tint bytes;\n\tint dir_count, size;\n\tstruct dir_ent *new_dir;\n\tstruct dir *dir;\n\n\tTRACE(\"squashfs_opendir: inode start block %d, offset %d\\n\", block_start, offset);\n\n\t*i = s_ops.read_inode(block_start, offset);\n\n\tdir = malloc(sizeof(struct dir));\n\tif (dir == NULL)\n\t\tEXIT_UNSQUASH(\"squashfs_opendir: malloc failed!\\n\");\n\n\tdir->dir_count = 0;\n\tdir->cur_entry = 0;\n\tdir->mode = (*i)->mode;\n\tdir->uid = (*i)->uid;\n\tdir->guid = (*i)->gid;\n\tdir->mtime = (*i)->time;\n\tdir->xattr = (*i)->xattr;\n\tdir->dirs = NULL;\n\n\tif ((*i)->data == 0)\n\t\t/*\n\t\t * if the directory is empty, skip the unnecessary\n\t\t * lookup_entry, this fixes the corner case with\n\t\t * completely empty filesystems where lookup_entry correctly\n\t\t * returning -1 is incorrectly treated as an error\n\t\t */\n\t\treturn dir;\n\n\tstart = sBlk.s.directory_table_start + (*i)->start;\n\tbytes = lookup_entry(directory_table_hash, start);\n\tif (bytes == -1)\n\t\tEXIT_UNSQUASH(\"squashfs_opendir: directory block %d not \" \"found!\\n\", block_start);\n\n\tbytes += (*i)->offset;\n\tsize = (*i)->data + bytes;\n\n\twhile (bytes < size) {\n\t\tif (swap) {\n\t\t\tsquashfs_dir_header_2 sdirh;\n\t\t\tmemcpy(&sdirh, directory_table + bytes, sizeof(sdirh));\n\t\t\tSQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);\n\t\t} else\n\t\t\tmemcpy(&dirh, directory_table + bytes, sizeof(dirh));\n\n\t\tdir_count = dirh.count + 1;\n\t\tTRACE(\"squashfs_opendir: Read directory header @ byte position \" \"%d, %d directory entries\\n\", bytes, dir_count);\n\t\tbytes += sizeof(dirh);\n\n\t\t/* dir_count should never be larger than 256 */\n\t\tif (dir_count > 256)\n\t\t\tgoto corrupted;\n\n\t\twhile (dir_count--) {\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_dir_entry_2 sdire;\n\t\t\t\tmemcpy(&sdire, directory_table + bytes, sizeof(sdire));\n\t\t\t\tSQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);\n\t\t\t} else\n\t\t\t\tmemcpy(dire, directory_table + bytes, sizeof(*dire));\n\t\t\tbytes += sizeof(*dire);\n\n\t\t\t/* size should never be larger than SQUASHFS_NAME_LEN */\n\t\t\tif (dire->size > SQUASHFS_NAME_LEN)\n\t\t\t\tgoto corrupted;\n\n\t\t\tmemcpy(dire->name, directory_table + bytes, dire->size + 1);\n\t\t\tdire->name[dire->size + 1] = '\\0';\n\t\t\tTRACE(\"squashfs_opendir: directory entry %s, inode \" \"%d:%d, type %d\\n\", dire->name, dirh.start_block, dire->offset, dire->type);\n\t\t\tif ((dir->dir_count % DIR_ENT_SIZE) == 0) {\n\t\t\t\tnew_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent));\n\t\t\t\tif (new_dir == NULL)\n\t\t\t\t\tEXIT_UNSQUASH(\"squashfs_opendir: \" \"realloc failed!\\n\");\n\t\t\t\tdir->dirs = new_dir;\n\t\t\t}\n\t\t\tstrcpy(dir->dirs[dir->dir_count].name, dire->name);\n\t\t\tdir->dirs[dir->dir_count].start_block = dirh.start_block;\n\t\t\tdir->dirs[dir->dir_count].offset = dire->offset;\n\t\t\tdir->dirs[dir->dir_count].type = dire->type;\n\t\t\tdir->dir_count++;\n\t\t\tbytes += dire->size + 1;\n\t\t}\n\t}\n\n\treturn dir;\n\n corrupted:\n\tfree(dir->dirs);\n\tfree(dir);\n\treturn NULL;\n}\n\nint read_uids_guids_1() {\n\tint res;\n\n\tTRACE(\"read_uids_guids: no_uids %d, no_guids %d\\n\", sBlk.no_uids, sBlk.no_guids);\n\n\tuid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int));\n\tif (uid_table == NULL) {\n\t\tERROR(\"read_uids_guids: failed to allocate uid/gid table\\n\");\n\t\treturn FALSE;\n\t}\n\n\tguid_table = uid_table + sBlk.no_uids;\n\n\tif (swap) {\n\t\tunsigned int suid_table[sBlk.no_uids + sBlk.no_guids];\n\n\t\tres = read_fs_bytes(fd, sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), suid_table);\n\t\tif (res == FALSE) {\n\t\t\tERROR(\"read_uids_guids: failed to read uid/gid table\" \"\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t\tSQUASHFS_SWAP_INTS_3(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids);\n\t} else {\n\t\tres = read_fs_bytes(fd, sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), uid_table);\n\t\tif (res == FALSE) {\n\t\t\tERROR(\"read_uids_guids: failed to read uid/gid table\" \"\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\treturn TRUE;\n}\n"
  },
  {
    "path": "src/squashfs/unsquash-2.c",
    "content": "/*\n * Unsquash a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2009, 2010, 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * unsquash-2.c\n */\n\n#include \"unsquashfs.h\"\n#include \"squashfs_compat.h\"\n\nstatic squashfs_fragment_entry_2 *fragment_table;\n\nvoid read_block_list_2(unsigned int *block_list, char *block_ptr, int blocks) {\n\tTRACE(\"read_block_list: blocks %d\\n\", blocks);\n\n\tif (swap) {\n\t\tunsigned int sblock_list[blocks];\n\t\tmemcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int));\n\t\tSQUASHFS_SWAP_INTS_3(block_list, sblock_list, blocks);\n\t} else\n\t\tmemcpy(block_list, block_ptr, blocks * sizeof(unsigned int));\n}\n\nint read_fragment_table_2(long long *directory_table_end) {\n\tint res, i;\n\tint bytes = SQUASHFS_FRAGMENT_BYTES_2(sBlk.s.fragments);\n\tint indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.s.fragments);\n\tunsigned int fragment_table_index[indexes];\n\n\tTRACE(\"read_fragment_table: %d fragments, reading %d fragment indexes \" \"from 0x%llx\\n\", sBlk.s.fragments, indexes, sBlk.s.fragment_table_start);\n\n\tif (sBlk.s.fragments == 0) {\n\t\t*directory_table_end = sBlk.s.fragment_table_start;\n\t\treturn TRUE;\n\t}\n\n\tfragment_table = malloc(bytes);\n\tif (fragment_table == NULL)\n\t\tEXIT_UNSQUASH(\"read_fragment_table: failed to allocate \" \"fragment table\\n\");\n\n\tif (swap) {\n\t\tunsigned int sfragment_table_index[indexes];\n\n\t\tres = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.s.fragments), sfragment_table_index);\n\t\tif (res == FALSE) {\n\t\t\tERROR(\"read_fragment_table: failed to read fragment \" \"table index\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t\tSQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes);\n\t} else {\n\t\tres = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.s.fragments), fragment_table_index);\n\t\tif (res == FALSE) {\n\t\t\tERROR(\"read_fragment_table: failed to read fragment \" \"table index\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\tfor (i = 0; i < indexes; i++) {\n\t\tint expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : bytes & (SQUASHFS_METADATA_SIZE - 1);\n\t\tint length = read_block(fd, fragment_table_index[i], NULL,\n\t\t\t\t\t\t\t\texpected, ((char *)fragment_table) + (i * SQUASHFS_METADATA_SIZE));\n\t\tTRACE(\"Read fragment table block %d, from 0x%x, length %d\\n\", i, fragment_table_index[i], length);\n\t\tif (length == FALSE) {\n\t\t\tERROR(\"read_fragment_table: failed to read fragment \" \"table block\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\tif (swap) {\n\t\tsquashfs_fragment_entry_2 sfragment;\n\t\tfor (i = 0; i < sBlk.s.fragments; i++) {\n\t\t\tSQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table[i]));\n\t\t\tmemcpy((char *)&fragment_table[i], (char *)&sfragment, sizeof(squashfs_fragment_entry_2));\n\t\t}\n\t}\n\n\t*directory_table_end = fragment_table_index[0];\n\treturn TRUE;\n}\n\nvoid read_fragment_2(unsigned int fragment, long long *start_block, int *size) {\n\tTRACE(\"read_fragment: reading fragment %d\\n\", fragment);\n\n\tsquashfs_fragment_entry_2 *fragment_entry = &fragment_table[fragment];\n\t*start_block = fragment_entry->start_block;\n\t*size = fragment_entry->size;\n}\n\nstruct inode *read_inode_2(unsigned int start_block, unsigned int offset) {\n\tstatic union squashfs_inode_header_2 header;\n\tlong long start = sBlk.s.inode_table_start + start_block;\n\tint bytes = lookup_entry(inode_table_hash, start);\n\tchar *block_ptr = inode_table + bytes + offset;\n\tstatic struct inode i;\n\n\tTRACE(\"read_inode: reading inode [%d:%d]\\n\", start_block, offset);\n\n\tif (bytes == -1)\n\t\tEXIT_UNSQUASH(\"read_inode: inode table block %lld not found\\n\", start);\n\n\tif (swap) {\n\t\tsquashfs_base_inode_header_2 sinode;\n\t\tmemcpy(&sinode, block_ptr, sizeof(header.base));\n\t\tSQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2));\n\t} else\n\t\tmemcpy(&header.base, block_ptr, sizeof(header.base));\n\n\ti.xattr = SQUASHFS_INVALID_XATTR;\n\ti.uid = (uid_t) uid_table[header.base.uid];\n\ti.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid];\n\ti.mode = lookup_type[header.base.inode_type] | header.base.mode;\n\ti.type = header.base.inode_type;\n\ti.time = sBlk.s.mkfs_time;\n\ti.inode_number = inode_number++;\n\n\tswitch (header.base.inode_type) {\n\tcase SQUASHFS_DIR_TYPE:{\n\t\t\tsquashfs_dir_inode_header_2 *inode = &header.dir;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_dir_inode_header_2 sinode;\n\t\t\t\tmemcpy(&sinode, block_ptr, sizeof(header.dir));\n\t\t\t\tSQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode);\n\t\t\t} else\n\t\t\t\tmemcpy(&header.dir, block_ptr, sizeof(header.dir));\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.time = inode->mtime;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_LDIR_TYPE:{\n\t\t\tsquashfs_ldir_inode_header_2 *inode = &header.ldir;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_ldir_inode_header_2 sinode;\n\t\t\t\tmemcpy(&sinode, block_ptr, sizeof(header.ldir));\n\t\t\t\tSQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode);\n\t\t\t} else\n\t\t\t\tmemcpy(&header.ldir, block_ptr, sizeof(header.ldir));\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.time = inode->mtime;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_FILE_TYPE:{\n\t\t\tsquashfs_reg_inode_header_2 *inode = &header.reg;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_reg_inode_header_2 sinode;\n\t\t\t\tmemcpy(&sinode, block_ptr, sizeof(sinode));\n\t\t\t\tSQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode);\n\t\t\t} else\n\t\t\t\tmemcpy(inode, block_ptr, sizeof(*inode));\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.time = inode->mtime;\n\t\t\ti.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size;\n\t\t\ti.fragment = inode->fragment;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log : i.data >> sBlk.s.block_log;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.sparse = 0;\n\t\t\ti.block_ptr = block_ptr + sizeof(*inode);\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_SYMLINK_TYPE:{\n\t\t\tsquashfs_symlink_inode_header_2 *inodep = &header.symlink;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_symlink_inode_header_2 sinodep;\n\t\t\t\tmemcpy(&sinodep, block_ptr, sizeof(sinodep));\n\t\t\t\tSQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep);\n\t\t\t} else\n\t\t\t\tmemcpy(inodep, block_ptr, sizeof(*inodep));\n\n\t\t\ti.symlink = malloc(inodep->symlink_size + 1);\n\t\t\tif (i.symlink == NULL)\n\t\t\t\tEXIT_UNSQUASH(\"read_inode: failed to malloc \" \"symlink data\\n\");\n\t\t\tstrncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size);\n\t\t\ti.symlink[inodep->symlink_size] = '\\0';\n\t\t\ti.data = inodep->symlink_size;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_BLKDEV_TYPE:\n\tcase SQUASHFS_CHRDEV_TYPE:{\n\t\t\tsquashfs_dev_inode_header_2 *inodep = &header.dev;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_dev_inode_header_2 sinodep;\n\t\t\t\tmemcpy(&sinodep, block_ptr, sizeof(sinodep));\n\t\t\t\tSQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep);\n\t\t\t} else\n\t\t\t\tmemcpy(inodep, block_ptr, sizeof(*inodep));\n\n\t\t\ti.data = inodep->rdev;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_FIFO_TYPE:\n\tcase SQUASHFS_SOCKET_TYPE:\n\t\ti.data = 0;\n\t\tbreak;\n\tdefault:\n\t\tEXIT_UNSQUASH(\"Unknown inode type %d in \" \"read_inode_header_2!\\n\", header.base.inode_type);\n\t}\n\treturn &i;\n}\n"
  },
  {
    "path": "src/squashfs/unsquash-3.c",
    "content": "/*\n * Unsquash a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2009, 2010, 2011, 2012, 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * unsquash-3.c\n */\n\n#include \"unsquashfs.h\"\n#include \"squashfs_compat.h\"\n\nstatic squashfs_fragment_entry_3 *fragment_table;\n\nint read_fragment_table_3(long long *directory_table_end) {\n\tint res, i;\n\tint bytes = SQUASHFS_FRAGMENT_BYTES_3(sBlk.s.fragments);\n\tint indexes = SQUASHFS_FRAGMENT_INDEXES_3(sBlk.s.fragments);\n\tlong long fragment_table_index[indexes];\n\n\tTRACE(\"read_fragment_table: %d fragments, reading %d fragment indexes \" \"from 0x%llx\\n\", sBlk.s.fragments, indexes, sBlk.s.fragment_table_start);\n\n\tif (sBlk.s.fragments == 0) {\n\t\t*directory_table_end = sBlk.s.fragment_table_start;\n\t\treturn TRUE;\n\t}\n\n\tfragment_table = malloc(bytes);\n\tif (fragment_table == NULL)\n\t\tEXIT_UNSQUASH(\"read_fragment_table: failed to allocate \" \"fragment table\\n\");\n\n\tif (swap) {\n\t\tlong long sfragment_table_index[indexes];\n\n\t\tres = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.s.fragments), sfragment_table_index);\n\t\tif (res == FALSE) {\n\t\t\tERROR(\"read_fragment_table: failed to read fragment \" \"table index\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t\tSQUASHFS_SWAP_FRAGMENT_INDEXES_3(fragment_table_index, sfragment_table_index, indexes);\n\t} else {\n\t\tres = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.s.fragments), fragment_table_index);\n\t\tif (res == FALSE) {\n\t\t\tERROR(\"read_fragment_table: failed to read fragment \" \"table index\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\tfor (i = 0; i < indexes; i++) {\n\t\tint expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : bytes & (SQUASHFS_METADATA_SIZE - 1);\n\t\tint length = read_block(fd, fragment_table_index[i], NULL,\n\t\t\t\t\t\t\t\texpected, ((char *)fragment_table) + (i * SQUASHFS_METADATA_SIZE));\n\t\tTRACE(\"Read fragment table block %d, from 0x%llx, length %d\\n\", i, fragment_table_index[i], length);\n\t\tif (length == FALSE) {\n\t\t\tERROR(\"read_fragment_table: failed to read fragment \" \"table block\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\tif (swap) {\n\t\tsquashfs_fragment_entry_3 sfragment;\n\t\tfor (i = 0; i < sBlk.s.fragments; i++) {\n\t\t\tSQUASHFS_SWAP_FRAGMENT_ENTRY_3((&sfragment), (&fragment_table[i]));\n\t\t\tmemcpy((char *)&fragment_table[i], (char *)&sfragment, sizeof(squashfs_fragment_entry_3));\n\t\t}\n\t}\n\n\t*directory_table_end = fragment_table_index[0];\n\treturn TRUE;\n}\n\nvoid read_fragment_3(unsigned int fragment, long long *start_block, int *size) {\n\tTRACE(\"read_fragment: reading fragment %d\\n\", fragment);\n\n\tsquashfs_fragment_entry_3 *fragment_entry = &fragment_table[fragment];\n\t*start_block = fragment_entry->start_block;\n\t*size = fragment_entry->size;\n}\n\nstruct inode *read_inode_3(unsigned int start_block, unsigned int offset) {\n\tstatic union squashfs_inode_header_3 header;\n\tlong long start = sBlk.s.inode_table_start + start_block;\n\tint bytes = lookup_entry(inode_table_hash, start);\n\tchar *block_ptr = inode_table + bytes + offset;\n\tstatic struct inode i;\n\n\tTRACE(\"read_inode: reading inode [%d:%d]\\n\", start_block, offset);\n\n\tif (bytes == -1)\n\t\tEXIT_UNSQUASH(\"read_inode: inode table block %lld not found\\n\", start);\n\n\tif (swap) {\n\t\tsquashfs_base_inode_header_3 sinode;\n\t\tmemcpy(&sinode, block_ptr, sizeof(header.base));\n\t\tSQUASHFS_SWAP_BASE_INODE_HEADER_3(&header.base, &sinode, sizeof(squashfs_base_inode_header_3));\n\t} else\n\t\tmemcpy(&header.base, block_ptr, sizeof(header.base));\n\n\ti.xattr = SQUASHFS_INVALID_XATTR;\n\ti.uid = (uid_t) uid_table[header.base.uid];\n\ti.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid];\n\ti.mode = lookup_type[header.base.inode_type] | header.base.mode;\n\ti.type = header.base.inode_type;\n\ti.time = header.base.mtime;\n\ti.inode_number = header.base.inode_number;\n\n\tswitch (header.base.inode_type) {\n\tcase SQUASHFS_DIR_TYPE:{\n\t\t\tsquashfs_dir_inode_header_3 *inode = &header.dir;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_dir_inode_header_3 sinode;\n\t\t\t\tmemcpy(&sinode, block_ptr, sizeof(header.dir));\n\t\t\t\tSQUASHFS_SWAP_DIR_INODE_HEADER_3(&header.dir, &sinode);\n\t\t\t} else\n\t\t\t\tmemcpy(&header.dir, block_ptr, sizeof(header.dir));\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.start = inode->start_block;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_LDIR_TYPE:{\n\t\t\tsquashfs_ldir_inode_header_3 *inode = &header.ldir;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_ldir_inode_header_3 sinode;\n\t\t\t\tmemcpy(&sinode, block_ptr, sizeof(header.ldir));\n\t\t\t\tSQUASHFS_SWAP_LDIR_INODE_HEADER_3(&header.ldir, &sinode);\n\t\t\t} else\n\t\t\t\tmemcpy(&header.ldir, block_ptr, sizeof(header.ldir));\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.start = inode->start_block;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_FILE_TYPE:{\n\t\t\tsquashfs_reg_inode_header_3 *inode = &header.reg;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_reg_inode_header_3 sinode;\n\t\t\t\tmemcpy(&sinode, block_ptr, sizeof(sinode));\n\t\t\t\tSQUASHFS_SWAP_REG_INODE_HEADER_3(inode, &sinode);\n\t\t\t} else\n\t\t\t\tmemcpy(inode, block_ptr, sizeof(*inode));\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size;\n\t\t\ti.fragment = inode->fragment;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log : i.data >> sBlk.s.block_log;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.sparse = 1;\n\t\t\ti.block_ptr = block_ptr + sizeof(*inode);\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_LREG_TYPE:{\n\t\t\tsquashfs_lreg_inode_header_3 *inode = &header.lreg;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_lreg_inode_header_3 sinode;\n\t\t\t\tmemcpy(&sinode, block_ptr, sizeof(sinode));\n\t\t\t\tSQUASHFS_SWAP_LREG_INODE_HEADER_3(inode, &sinode);\n\t\t\t} else\n\t\t\t\tmemcpy(inode, block_ptr, sizeof(*inode));\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size;\n\t\t\ti.fragment = inode->fragment;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.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;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.sparse = 1;\n\t\t\ti.block_ptr = block_ptr + sizeof(*inode);\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_SYMLINK_TYPE:{\n\t\t\tsquashfs_symlink_inode_header_3 *inodep = &header.symlink;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_symlink_inode_header_3 sinodep;\n\t\t\t\tmemcpy(&sinodep, block_ptr, sizeof(sinodep));\n\t\t\t\tSQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(inodep, &sinodep);\n\t\t\t} else\n\t\t\t\tmemcpy(inodep, block_ptr, sizeof(*inodep));\n\n\t\t\ti.symlink = malloc(inodep->symlink_size + 1);\n\t\t\tif (i.symlink == NULL)\n\t\t\t\tEXIT_UNSQUASH(\"read_inode: failed to malloc \" \"symlink data\\n\");\n\t\t\tstrncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_3), inodep->symlink_size);\n\t\t\ti.symlink[inodep->symlink_size] = '\\0';\n\t\t\ti.data = inodep->symlink_size;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_BLKDEV_TYPE:\n\tcase SQUASHFS_CHRDEV_TYPE:{\n\t\t\tsquashfs_dev_inode_header_3 *inodep = &header.dev;\n\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_dev_inode_header_3 sinodep;\n\t\t\t\tmemcpy(&sinodep, block_ptr, sizeof(sinodep));\n\t\t\t\tSQUASHFS_SWAP_DEV_INODE_HEADER_3(inodep, &sinodep);\n\t\t\t} else\n\t\t\t\tmemcpy(inodep, block_ptr, sizeof(*inodep));\n\n\t\t\ti.data = inodep->rdev;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_FIFO_TYPE:\n\tcase SQUASHFS_SOCKET_TYPE:\n\t\ti.data = 0;\n\t\tbreak;\n\tdefault:\n\t\tEXIT_UNSQUASH(\"Unknown inode type %d in read_inode!\\n\", header.base.inode_type);\n\t}\n\treturn &i;\n}\n\nstruct dir *squashfs_opendir_3(unsigned int block_start, unsigned int offset, struct inode **i) {\n\tsquashfs_dir_header_3 dirh;\n\tchar buffer[sizeof(squashfs_dir_entry_3) + SQUASHFS_NAME_LEN + 1]\n\t\t__attribute__ ((aligned));\n\tsquashfs_dir_entry_3 *dire = (squashfs_dir_entry_3 *) buffer;\n\tlong long start;\n\tint bytes;\n\tint dir_count, size;\n\tstruct dir_ent *new_dir;\n\tstruct dir *dir;\n\n\tTRACE(\"squashfs_opendir: inode start block %d, offset %d\\n\", block_start, offset);\n\n\t*i = s_ops.read_inode(block_start, offset);\n\n\tdir = malloc(sizeof(struct dir));\n\tif (dir == NULL)\n\t\tEXIT_UNSQUASH(\"squashfs_opendir: malloc failed!\\n\");\n\n\tdir->dir_count = 0;\n\tdir->cur_entry = 0;\n\tdir->mode = (*i)->mode;\n\tdir->uid = (*i)->uid;\n\tdir->guid = (*i)->gid;\n\tdir->mtime = (*i)->time;\n\tdir->xattr = (*i)->xattr;\n\tdir->dirs = NULL;\n\n\tif ((*i)->data == 3)\n\t\t/*\n\t\t * if the directory is empty, skip the unnecessary\n\t\t * lookup_entry, this fixes the corner case with\n\t\t * completely empty filesystems where lookup_entry correctly\n\t\t * returning -1 is incorrectly treated as an error\n\t\t */\n\t\treturn dir;\n\n\tstart = sBlk.s.directory_table_start + (*i)->start;\n\tbytes = lookup_entry(directory_table_hash, start);\n\n\tif (bytes == -1)\n\t\tEXIT_UNSQUASH(\"squashfs_opendir: directory block %d not \" \"found!\\n\", block_start);\n\n\tbytes += (*i)->offset;\n\tsize = (*i)->data + bytes - 3;\n\n\twhile (bytes < size) {\n\t\tif (swap) {\n\t\t\tsquashfs_dir_header_3 sdirh;\n\t\t\tmemcpy(&sdirh, directory_table + bytes, sizeof(sdirh));\n\t\t\tSQUASHFS_SWAP_DIR_HEADER_3(&dirh, &sdirh);\n\t\t} else\n\t\t\tmemcpy(&dirh, directory_table + bytes, sizeof(dirh));\n\n\t\tdir_count = dirh.count + 1;\n\t\tTRACE(\"squashfs_opendir: Read directory header @ byte position \" \"%d, %d directory entries\\n\", bytes, dir_count);\n\t\tbytes += sizeof(dirh);\n\n\t\t/* dir_count should never be larger than 256 */\n\t\tif (dir_count > 256)\n\t\t\tgoto corrupted;\n\n\t\twhile (dir_count--) {\n\t\t\tif (swap) {\n\t\t\t\tsquashfs_dir_entry_3 sdire;\n\t\t\t\tmemcpy(&sdire, directory_table + bytes, sizeof(sdire));\n\t\t\t\tSQUASHFS_SWAP_DIR_ENTRY_3(dire, &sdire);\n\t\t\t} else\n\t\t\t\tmemcpy(dire, directory_table + bytes, sizeof(*dire));\n\t\t\tbytes += sizeof(*dire);\n\n\t\t\t/* size should never be larger than SQUASHFS_NAME_LEN */\n\t\t\tif (dire->size > SQUASHFS_NAME_LEN)\n\t\t\t\tgoto corrupted;\n\n\t\t\tmemcpy(dire->name, directory_table + bytes, dire->size + 1);\n\t\t\tdire->name[dire->size + 1] = '\\0';\n\t\t\tTRACE(\"squashfs_opendir: directory entry %s, inode \" \"%d:%d, type %d\\n\", dire->name, dirh.start_block, dire->offset, dire->type);\n\t\t\tif ((dir->dir_count % DIR_ENT_SIZE) == 0) {\n\t\t\t\tnew_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent));\n\t\t\t\tif (new_dir == NULL)\n\t\t\t\t\tEXIT_UNSQUASH(\"squashfs_opendir: \" \"realloc failed!\\n\");\n\t\t\t\tdir->dirs = new_dir;\n\t\t\t}\n\t\t\tstrcpy(dir->dirs[dir->dir_count].name, dire->name);\n\t\t\tdir->dirs[dir->dir_count].start_block = dirh.start_block;\n\t\t\tdir->dirs[dir->dir_count].offset = dire->offset;\n\t\t\tdir->dirs[dir->dir_count].type = dire->type;\n\t\t\tdir->dir_count++;\n\t\t\tbytes += dire->size + 1;\n\t\t}\n\t}\n\n\treturn dir;\n\n corrupted:\n\tfree(dir->dirs);\n\tfree(dir);\n\treturn NULL;\n}\n"
  },
  {
    "path": "src/squashfs/unsquash-4.c",
    "content": "/*\n * Unsquash a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2009, 2010, 2011, 2012, 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * unsquash-4.c\n */\n\n#include \"unsquashfs.h\"\n#include \"squashfs_swap.h\"\n\nstatic struct squashfs_fragment_entry *fragment_table;\nstatic unsigned int *id_table;\n\nint read_fragment_table_4(long long *directory_table_end) {\n\tint res, i;\n\tint bytes = SQUASHFS_FRAGMENT_BYTES(sBlk.s.fragments);\n\tint indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.s.fragments);\n\tlong long fragment_table_index[indexes];\n\n\tTRACE(\"read_fragment_table: %d fragments, reading %d fragment indexes \" \"from 0x%llx\\n\", sBlk.s.fragments, indexes, sBlk.s.fragment_table_start);\n\n\tif (sBlk.s.fragments == 0) {\n\t\t*directory_table_end = sBlk.s.fragment_table_start;\n\t\treturn TRUE;\n\t}\n\n\tfragment_table = malloc(bytes);\n\tif (fragment_table == NULL)\n\t\tEXIT_UNSQUASH(\"read_fragment_table: failed to allocate \" \"fragment table\\n\");\n\n\tres = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.s.fragments), fragment_table_index);\n\tif (res == FALSE) {\n\t\tERROR(\"read_fragment_table: failed to read fragment table \" \"index\\n\");\n\t\treturn FALSE;\n\t}\n\tSQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes);\n\n\tfor (i = 0; i < indexes; i++) {\n\t\tint expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : bytes & (SQUASHFS_METADATA_SIZE - 1);\n\t\tint length = read_block(fd, fragment_table_index[i], NULL,\n\t\t\t\t\t\t\t\texpected, ((char *)fragment_table) + (i * SQUASHFS_METADATA_SIZE));\n\t\tTRACE(\"Read fragment table block %d, from 0x%llx, length %d\\n\", i, fragment_table_index[i], length);\n\t\tif (length == FALSE) {\n\t\t\tERROR(\"read_fragment_table: failed to read fragment \" \"table index\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\tfor (i = 0; i < sBlk.s.fragments; i++)\n\t\tSQUASHFS_INSWAP_FRAGMENT_ENTRY(&fragment_table[i]);\n\n\t*directory_table_end = fragment_table_index[0];\n\treturn TRUE;\n}\n\nvoid read_fragment_4(unsigned int fragment, long long *start_block, int *size) {\n\tTRACE(\"read_fragment: reading fragment %d\\n\", fragment);\n\n\tstruct squashfs_fragment_entry *fragment_entry;\n\n\tfragment_entry = &fragment_table[fragment];\n\t*start_block = fragment_entry->start_block;\n\t*size = fragment_entry->size;\n}\n\nstruct inode *read_inode_4(unsigned int start_block, unsigned int offset) {\n\tstatic union squashfs_inode_header header;\n\tlong long start = sBlk.s.inode_table_start + start_block;\n\tint bytes = lookup_entry(inode_table_hash, start);\n\tchar *block_ptr = inode_table + bytes + offset;\n\tstatic struct inode i;\n\n\tTRACE(\"read_inode: reading inode [%d:%d]\\n\", start_block, offset);\n\n\tif (bytes == -1)\n\t\tEXIT_UNSQUASH(\"read_inode: inode table block %lld not found\\n\", start);\n\n\tSQUASHFS_SWAP_BASE_INODE_HEADER(block_ptr, &header.base);\n\n\ti.uid = (uid_t) id_table[header.base.uid];\n\ti.gid = (uid_t) id_table[header.base.guid];\n\ti.mode = lookup_type[header.base.inode_type] | header.base.mode;\n\ti.type = header.base.inode_type;\n\ti.time = header.base.mtime;\n\ti.inode_number = header.base.inode_number;\n\n\tswitch (header.base.inode_type) {\n\tcase SQUASHFS_DIR_TYPE:{\n\t\t\tstruct squashfs_dir_inode_header *inode = &header.dir;\n\n\t\t\tSQUASHFS_SWAP_DIR_INODE_HEADER(block_ptr, inode);\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.xattr = SQUASHFS_INVALID_XATTR;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_LDIR_TYPE:{\n\t\t\tstruct squashfs_ldir_inode_header *inode = &header.ldir;\n\n\t\t\tSQUASHFS_SWAP_LDIR_INODE_HEADER(block_ptr, inode);\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.xattr = inode->xattr;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_FILE_TYPE:{\n\t\t\tstruct squashfs_reg_inode_header *inode = &header.reg;\n\n\t\t\tSQUASHFS_SWAP_REG_INODE_HEADER(block_ptr, inode);\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size;\n\t\t\ti.fragment = inode->fragment;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log : i.data >> sBlk.s.block_log;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.sparse = 0;\n\t\t\ti.block_ptr = block_ptr + sizeof(*inode);\n\t\t\ti.xattr = SQUASHFS_INVALID_XATTR;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_LREG_TYPE:{\n\t\t\tstruct squashfs_lreg_inode_header *inode = &header.lreg;\n\n\t\t\tSQUASHFS_SWAP_LREG_INODE_HEADER(block_ptr, inode);\n\n\t\t\ti.data = inode->file_size;\n\t\t\ti.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size;\n\t\t\ti.fragment = inode->fragment;\n\t\t\ti.offset = inode->offset;\n\t\t\ti.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;\n\t\t\ti.start = inode->start_block;\n\t\t\ti.sparse = inode->sparse != 0;\n\t\t\ti.block_ptr = block_ptr + sizeof(*inode);\n\t\t\ti.xattr = inode->xattr;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_SYMLINK_TYPE:\n\tcase SQUASHFS_LSYMLINK_TYPE:{\n\t\t\tstruct squashfs_symlink_inode_header *inode = &header.symlink;\n\n\t\t\tSQUASHFS_SWAP_SYMLINK_INODE_HEADER(block_ptr, inode);\n\n\t\t\ti.symlink = malloc(inode->symlink_size + 1);\n\t\t\tif (i.symlink == NULL)\n\t\t\t\tEXIT_UNSQUASH(\"read_inode: failed to malloc \" \"symlink data\\n\");\n\t\t\tstrncpy(i.symlink, block_ptr + sizeof(struct squashfs_symlink_inode_header), inode->symlink_size);\n\t\t\ti.symlink[inode->symlink_size] = '\\0';\n\t\t\ti.data = inode->symlink_size;\n\n\t\t\tif (header.base.inode_type == SQUASHFS_LSYMLINK_TYPE)\n\t\t\t\tSQUASHFS_SWAP_INTS(block_ptr + sizeof(struct squashfs_symlink_inode_header) + inode->symlink_size, &i.xattr, 1);\n\t\t\telse\n\t\t\t\ti.xattr = SQUASHFS_INVALID_XATTR;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_BLKDEV_TYPE:\n\tcase SQUASHFS_CHRDEV_TYPE:{\n\t\t\tstruct squashfs_dev_inode_header *inode = &header.dev;\n\n\t\t\tSQUASHFS_SWAP_DEV_INODE_HEADER(block_ptr, inode);\n\n\t\t\ti.data = inode->rdev;\n\t\t\ti.xattr = SQUASHFS_INVALID_XATTR;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_LBLKDEV_TYPE:\n\tcase SQUASHFS_LCHRDEV_TYPE:{\n\t\t\tstruct squashfs_ldev_inode_header *inode = &header.ldev;\n\n\t\t\tSQUASHFS_SWAP_LDEV_INODE_HEADER(block_ptr, inode);\n\n\t\t\ti.data = inode->rdev;\n\t\t\ti.xattr = inode->xattr;\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_FIFO_TYPE:\n\tcase SQUASHFS_SOCKET_TYPE:\n\t\ti.data = 0;\n\t\ti.xattr = SQUASHFS_INVALID_XATTR;\n\t\tbreak;\n\tcase SQUASHFS_LFIFO_TYPE:\n\tcase SQUASHFS_LSOCKET_TYPE:{\n\t\t\tstruct squashfs_lipc_inode_header *inode = &header.lipc;\n\n\t\t\tSQUASHFS_SWAP_LIPC_INODE_HEADER(block_ptr, inode);\n\n\t\t\ti.data = 0;\n\t\t\ti.xattr = inode->xattr;\n\t\t\tbreak;\n\t\t}\n\tdefault:\n\t\tEXIT_UNSQUASH(\"Unknown inode type %d in read_inode!\\n\", header.base.inode_type);\n\t}\n\treturn &i;\n}\n\nstruct dir *squashfs_opendir_4(unsigned int block_start, unsigned int offset, struct inode **i) {\n\tstruct squashfs_dir_header dirh;\n\tchar buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]\n\t\t__attribute__ ((aligned));\n\tstruct squashfs_dir_entry *dire = (struct squashfs_dir_entry *)buffer;\n\tlong long start;\n\tint bytes;\n\tint dir_count, size;\n\tstruct dir_ent *new_dir;\n\tstruct dir *dir;\n\n\tTRACE(\"squashfs_opendir: inode start block %d, offset %d\\n\", block_start, offset);\n\n\t*i = s_ops.read_inode(block_start, offset);\n\n\tdir = malloc(sizeof(struct dir));\n\tif (dir == NULL)\n\t\tEXIT_UNSQUASH(\"squashfs_opendir: malloc failed!\\n\");\n\n\tdir->dir_count = 0;\n\tdir->cur_entry = 0;\n\tdir->mode = (*i)->mode;\n\tdir->uid = (*i)->uid;\n\tdir->guid = (*i)->gid;\n\tdir->mtime = (*i)->time;\n\tdir->xattr = (*i)->xattr;\n\tdir->dirs = NULL;\n\n\tif ((*i)->data == 3)\n\t\t/*\n\t\t * if the directory is empty, skip the unnecessary\n\t\t * lookup_entry, this fixes the corner case with\n\t\t * completely empty filesystems where lookup_entry correctly\n\t\t * returning -1 is incorrectly treated as an error\n\t\t */\n\t\treturn dir;\n\n\tstart = sBlk.s.directory_table_start + (*i)->start;\n\tbytes = lookup_entry(directory_table_hash, start);\n\n\tif (bytes == -1)\n\t\tEXIT_UNSQUASH(\"squashfs_opendir: directory block %d not \" \"found!\\n\", block_start);\n\n\tbytes += (*i)->offset;\n\tsize = (*i)->data + bytes - 3;\n\n\twhile (bytes < size) {\n\t\tSQUASHFS_SWAP_DIR_HEADER(directory_table + bytes, &dirh);\n\n\t\tdir_count = dirh.count + 1;\n\t\tTRACE(\"squashfs_opendir: Read directory header @ byte position \" \"%d, %d directory entries\\n\", bytes, dir_count);\n\t\tbytes += sizeof(dirh);\n\n\t\t/* dir_count should never be larger than 256 */\n\t\tif (dir_count > 256)\n\t\t\tgoto corrupted;\n\n\t\twhile (dir_count--) {\n\t\t\tSQUASHFS_SWAP_DIR_ENTRY(directory_table + bytes, dire);\n\n\t\t\tbytes += sizeof(*dire);\n\n\t\t\t/* size should never be larger than SQUASHFS_NAME_LEN */\n\t\t\tif (dire->size > SQUASHFS_NAME_LEN)\n\t\t\t\tgoto corrupted;\n\n\t\t\tmemcpy(dire->name, directory_table + bytes, dire->size + 1);\n\t\t\tdire->name[dire->size + 1] = '\\0';\n\t\t\tTRACE(\"squashfs_opendir: directory entry %s, inode \" \"%d:%d, type %d\\n\", dire->name, dirh.start_block, dire->offset, dire->type);\n\t\t\tif ((dir->dir_count % DIR_ENT_SIZE) == 0) {\n\t\t\t\tnew_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent));\n\t\t\t\tif (new_dir == NULL)\n\t\t\t\t\tEXIT_UNSQUASH(\"squashfs_opendir: \" \"realloc failed!\\n\");\n\t\t\t\tdir->dirs = new_dir;\n\t\t\t}\n\t\t\tstrcpy(dir->dirs[dir->dir_count].name, dire->name);\n\t\t\tdir->dirs[dir->dir_count].start_block = dirh.start_block;\n\t\t\tdir->dirs[dir->dir_count].offset = dire->offset;\n\t\t\tdir->dirs[dir->dir_count].type = dire->type;\n\t\t\tdir->dir_count++;\n\t\t\tbytes += dire->size + 1;\n\t\t}\n\t}\n\n\treturn dir;\n\n corrupted:\n\tfree(dir->dirs);\n\tfree(dir);\n\treturn NULL;\n}\n\nint read_uids_guids_4() {\n\tint res, i;\n\tint bytes = SQUASHFS_ID_BYTES(sBlk.s.no_ids);\n\tint indexes = SQUASHFS_ID_BLOCKS(sBlk.s.no_ids);\n\tlong long id_index_table[indexes];\n\n\tTRACE(\"read_uids_guids: no_ids %d\\n\", sBlk.s.no_ids);\n\n\tid_table = malloc(bytes);\n\tif (id_table == NULL) {\n\t\tERROR(\"read_uids_guids: failed to allocate id table\\n\");\n\t\treturn FALSE;\n\t}\n\n\tres = read_fs_bytes(fd, sBlk.s.id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk.s.no_ids), id_index_table);\n\tif (res == FALSE) {\n\t\tERROR(\"read_uids_guids: failed to read id index table\\n\");\n\t\treturn FALSE;\n\t}\n\tSQUASHFS_INSWAP_ID_BLOCKS(id_index_table, indexes);\n\n\tfor (i = 0; i < indexes; i++) {\n\t\tint expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : bytes & (SQUASHFS_METADATA_SIZE - 1);\n\t\tres = read_block(fd, id_index_table[i], NULL, expected, ((char *)id_table) + i * SQUASHFS_METADATA_SIZE);\n\t\tif (res == FALSE) {\n\t\t\tERROR(\"read_uids_guids: failed to read id table block\" \"\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\tSQUASHFS_INSWAP_INTS(id_table, sBlk.s.no_ids);\n\n\treturn TRUE;\n}\n"
  },
  {
    "path": "src/squashfs/unsquashfs.c",
    "content": "/*\n * Unsquash a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,\n * 2012, 2013, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * unsquashfs.c\n */\n\n#include \"unsquashfs.h\"\n#include \"squashfs_swap.h\"\n#include \"squashfs_compat.h\"\n#include \"compressor.h\"\n#include \"xattr.h\"\n#include \"unsquashfs_info.h\"\n#include \"stdarg.h\"\n\n#ifdef __APPLE__\n#    include <sys/sysctl.h>\n#else\n#    include <sys/sysinfo.h>\n#endif\n\n#include <poll.h>\n#include <sys/types.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n#include <limits.h>\n#include <ctype.h>\n#include <stdint.h>\n\nstruct cache *fragment_cache, *data_cache;\nstruct queue *to_reader, *to_inflate, *to_writer, *from_writer;\npthread_t *thread, *inflator_thread;\npthread_mutex_t fragment_mutex;\n\n/* user options that control parallelisation */\nint processors = -1;\n\nstruct super_block sBlk;\nsquashfs_operations s_ops;\nstruct compressor *comp;\n\nint bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0;\nchar *inode_table = NULL, *directory_table = NULL;\nstruct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536];\nint fd;\nunsigned int *uid_table, *guid_table;\nunsigned int cached_frag = SQUASHFS_INVALID_FRAG;\nchar *fragment_data;\nchar *file_data;\nchar *data;\nunsigned int block_size;\nunsigned int block_log;\nint lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE;\nint use_regex = FALSE;\nchar **created_inode;\nint root_process;\nint columns;\nint rotate = 0;\npthread_mutex_t screen_mutex;\nint progress = TRUE, progress_enabled = FALSE;\nunsigned int total_blocks = 0, total_files = 0, total_inodes = 0;\nunsigned int cur_blocks = 0;\nint inode_number = 1;\nint no_xattrs = XATTR_DEF;\nint user_xattrs = FALSE;\n\nint lookup_type[] = {\n\t0,\n\tS_IFDIR,\n\tS_IFREG,\n\tS_IFLNK,\n\tS_IFBLK,\n\tS_IFCHR,\n\tS_IFIFO,\n\tS_IFSOCK,\n\tS_IFDIR,\n\tS_IFREG,\n\tS_IFLNK,\n\tS_IFBLK,\n\tS_IFCHR,\n\tS_IFIFO,\n\tS_IFSOCK\n};\n\nstruct test table[] = {\n\t{S_IFMT, S_IFSOCK, 0, 's'},\n\t{S_IFMT, S_IFLNK, 0, 'l'},\n\t{S_IFMT, S_IFBLK, 0, 'b'},\n\t{S_IFMT, S_IFDIR, 0, 'd'},\n\t{S_IFMT, S_IFCHR, 0, 'c'},\n\t{S_IFMT, S_IFIFO, 0, 'p'},\n\t{S_IRUSR, S_IRUSR, 1, 'r'},\n\t{S_IWUSR, S_IWUSR, 2, 'w'},\n\t{S_IRGRP, S_IRGRP, 4, 'r'},\n\t{S_IWGRP, S_IWGRP, 5, 'w'},\n\t{S_IROTH, S_IROTH, 7, 'r'},\n\t{S_IWOTH, S_IWOTH, 8, 'w'},\n\t{S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's'},\n\t{S_IXUSR | S_ISUID, S_ISUID, 3, 'S'},\n\t{S_IXUSR | S_ISUID, S_IXUSR, 3, 'x'},\n\t{S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's'},\n\t{S_IXGRP | S_ISGID, S_ISGID, 6, 'S'},\n\t{S_IXGRP | S_ISGID, S_IXGRP, 6, 'x'},\n\t{S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't'},\n\t{S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T'},\n\t{S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x'},\n\t{0, 0, 0, 0}\n};\n\nvoid progress_bar(long long current, long long max, int columns);\n\n#define MAX_LINE 16384\n\nvoid prep_exit() {\n}\n\nvoid sigwinch_handler() {\n\tstruct winsize winsize;\n\n\tif (ioctl(1, TIOCGWINSZ, &winsize) == -1) {\n\t\tif (isatty(STDOUT_FILENO))\n\t\t\tERROR(\"TIOCGWINSZ ioctl failed, defaulting to 80 \" \"columns\\n\");\n\t\tcolumns = 80;\n\t} else\n\t\tcolumns = winsize.ws_col;\n}\n\nvoid sigalrm_handler() {\n\trotate = (rotate + 1) % 4;\n}\n\nint add_overflow(int a, int b) {\n\treturn (INT_MAX - a) < b;\n}\n\nint shift_overflow(int a, int shift) {\n\treturn (INT_MAX >> shift) < a;\n}\n\nint multiply_overflow(int a, int multiplier) {\n\treturn (INT_MAX / multiplier) < a;\n}\n\nstruct queue *queue_init(int size) {\n\tstruct queue *queue = malloc(sizeof(struct queue));\n\n\tif (queue == NULL)\n\t\tEXIT_UNSQUASH(\"Out of memory in queue_init\\n\");\n\n\tif (add_overflow(size, 1) || multiply_overflow(size + 1, sizeof(void *)))\n\t\tEXIT_UNSQUASH(\"Size too large in queue_init\\n\");\n\n\tqueue->data = malloc(sizeof(void *) * (size + 1));\n\tif (queue->data == NULL)\n\t\tEXIT_UNSQUASH(\"Out of memory in queue_init\\n\");\n\n\tqueue->size = size + 1;\n\tqueue->readp = queue->writep = 0;\n\tpthread_mutex_init(&queue->mutex, NULL);\n\tpthread_cond_init(&queue->empty, NULL);\n\tpthread_cond_init(&queue->full, NULL);\n\n\treturn queue;\n}\n\nvoid queue_put(struct queue *queue, void *data) {\n\tint nextp;\n\n\tpthread_mutex_lock(&queue->mutex);\n\n\twhile ((nextp = (queue->writep + 1) % queue->size) == queue->readp)\n\t\tpthread_cond_wait(&queue->full, &queue->mutex);\n\n\tqueue->data[queue->writep] = data;\n\tqueue->writep = nextp;\n\tpthread_cond_signal(&queue->empty);\n\tpthread_mutex_unlock(&queue->mutex);\n}\n\nvoid *queue_get(struct queue *queue) {\n\tvoid *data;\n\tpthread_mutex_lock(&queue->mutex);\n\n\twhile (queue->readp == queue->writep)\n\t\tpthread_cond_wait(&queue->empty, &queue->mutex);\n\n\tdata = queue->data[queue->readp];\n\tqueue->readp = (queue->readp + 1) % queue->size;\n\tpthread_cond_signal(&queue->full);\n\tpthread_mutex_unlock(&queue->mutex);\n\n\treturn data;\n}\n\nvoid dump_queue(struct queue *queue) {\n\tpthread_mutex_lock(&queue->mutex);\n\n\tprintf(\"Max size %d, size %d%s\\n\", queue->size - 1, queue->readp <= queue->writep ? queue->writep - queue->readp : queue->size - queue->readp + queue->writep, queue->readp == queue->writep ? \" (EMPTY)\" : ((queue->writep + 1) % queue->size) == queue->readp ? \" (FULL)\" : \"\");\n\n\tpthread_mutex_unlock(&queue->mutex);\n}\n\n/* Called with the cache mutex held */\nvoid insert_hash_table(struct cache *cache, struct cache_entry *entry) {\n\tint hash = CALCULATE_HASH(entry->block);\n\n\tentry->hash_next = cache->hash_table[hash];\n\tcache->hash_table[hash] = entry;\n\tentry->hash_prev = NULL;\n\tif (entry->hash_next)\n\t\tentry->hash_next->hash_prev = entry;\n}\n\n/* Called with the cache mutex held */\nvoid remove_hash_table(struct cache *cache, struct cache_entry *entry) {\n\tif (entry->hash_prev)\n\t\tentry->hash_prev->hash_next = entry->hash_next;\n\telse\n\t\tcache->hash_table[CALCULATE_HASH(entry->block)] = entry->hash_next;\n\tif (entry->hash_next)\n\t\tentry->hash_next->hash_prev = entry->hash_prev;\n\n\tentry->hash_prev = entry->hash_next = NULL;\n}\n\n/* Called with the cache mutex held */\nvoid insert_free_list(struct cache *cache, struct cache_entry *entry) {\n\tif (cache->free_list) {\n\t\tentry->free_next = cache->free_list;\n\t\tentry->free_prev = cache->free_list->free_prev;\n\t\tcache->free_list->free_prev->free_next = entry;\n\t\tcache->free_list->free_prev = entry;\n\t} else {\n\t\tcache->free_list = entry;\n\t\tentry->free_prev = entry->free_next = entry;\n\t}\n}\n\n/* Called with the cache mutex held */\nvoid remove_free_list(struct cache *cache, struct cache_entry *entry) {\n\tif (entry->free_prev == NULL || entry->free_next == NULL)\n\t\t/* not in free list */\n\t\treturn;\n\telse if (entry->free_prev == entry && entry->free_next == entry) {\n\t\t/* only this entry in the free list */\n\t\tcache->free_list = NULL;\n\t} else {\n\t\t/* more than one entry in the free list */\n\t\tentry->free_next->free_prev = entry->free_prev;\n\t\tentry->free_prev->free_next = entry->free_next;\n\t\tif (cache->free_list == entry)\n\t\t\tcache->free_list = entry->free_next;\n\t}\n\n\tentry->free_prev = entry->free_next = NULL;\n}\n\nstruct cache *cache_init(int buffer_size, int max_buffers) {\n\tstruct cache *cache = malloc(sizeof(struct cache));\n\n\tif (cache == NULL)\n\t\tEXIT_UNSQUASH(\"Out of memory in cache_init\\n\");\n\n\tcache->max_buffers = max_buffers;\n\tcache->buffer_size = buffer_size;\n\tcache->count = 0;\n\tcache->used = 0;\n\tcache->free_list = NULL;\n\tmemset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536);\n\tcache->wait_free = FALSE;\n\tcache->wait_pending = FALSE;\n\tpthread_mutex_init(&cache->mutex, NULL);\n\tpthread_cond_init(&cache->wait_for_free, NULL);\n\tpthread_cond_init(&cache->wait_for_pending, NULL);\n\n\treturn cache;\n}\n\nstruct cache_entry *cache_get(struct cache *cache, long long block, int size) {\n\t/*\n\t * Get a block out of the cache.  If the block isn't in the cache\n\t * it is added and queued to the reader() and inflate() threads for\n\t * reading off disk and decompression.  The cache grows until max_blocks\n\t * is reached, once this occurs existing discarded blocks on the free\n\t * list are reused\n\t */\n\tint hash = CALCULATE_HASH(block);\n\tstruct cache_entry *entry;\n\n\tpthread_mutex_lock(&cache->mutex);\n\n\tfor (entry = cache->hash_table[hash]; entry; entry = entry->hash_next)\n\t\tif (entry->block == block)\n\t\t\tbreak;\n\n\tif (entry) {\n\t\t/*\n\t\t * found the block in the cache.  If the block is currently unused\n\t\t * remove it from the free list and increment cache used count.\n\t\t */\n\t\tif (entry->used == 0) {\n\t\t\tcache->used++;\n\t\t\tremove_free_list(cache, entry);\n\t\t}\n\t\tentry->used++;\n\t\tpthread_mutex_unlock(&cache->mutex);\n\t} else {\n\t\t/*\n\t\t * not in the cache\n\t\t *\n\t\t * first try to allocate new block\n\t\t */\n\t\tif (cache->count < cache->max_buffers) {\n\t\t\tentry = malloc(sizeof(struct cache_entry));\n\t\t\tif (entry == NULL)\n\t\t\t\tEXIT_UNSQUASH(\"Out of memory in cache_get\\n\");\n\t\t\tentry->data = malloc(cache->buffer_size);\n\t\t\tif (entry->data == NULL)\n\t\t\t\tEXIT_UNSQUASH(\"Out of memory in cache_get\\n\");\n\t\t\tentry->cache = cache;\n\t\t\tentry->free_prev = entry->free_next = NULL;\n\t\t\tcache->count++;\n\t\t} else {\n\t\t\t/*\n\t\t\t * try to get from free list\n\t\t\t */\n\t\t\twhile (cache->free_list == NULL) {\n\t\t\t\tcache->wait_free = TRUE;\n\t\t\t\tpthread_cond_wait(&cache->wait_for_free, &cache->mutex);\n\t\t\t}\n\t\t\tentry = cache->free_list;\n\t\t\tremove_free_list(cache, entry);\n\t\t\tremove_hash_table(cache, entry);\n\t\t}\n\n\t\t/*\n\t\t * Initialise block and insert into the hash table.\n\t\t * Increment used which tracks how many buffers in the\n\t\t * cache are actively in use (the other blocks, count - used,\n\t\t * are in the cache and available for lookup, but can also be\n\t\t * re-used).\n\t\t */\n\t\tentry->block = block;\n\t\tentry->size = size;\n\t\tentry->used = 1;\n\t\tentry->error = FALSE;\n\t\tentry->pending = TRUE;\n\t\tinsert_hash_table(cache, entry);\n\t\tcache->used++;\n\n\t\t/*\n\t\t * queue to read thread to read and ultimately (via the\n\t\t * decompress threads) decompress the buffer\n\t\t */\n\t\tpthread_mutex_unlock(&cache->mutex);\n\t\tqueue_put(to_reader, entry);\n\t}\n\n\treturn entry;\n}\n\nvoid cache_block_ready(struct cache_entry *entry, int error) {\n\t/*\n\t * mark cache entry as being complete, reading and (if necessary)\n\t * decompression has taken place, and the buffer is valid for use.\n\t * If an error occurs reading or decompressing, the buffer also\n\t * becomes ready but with an error...\n\t */\n\tpthread_mutex_lock(&entry->cache->mutex);\n\tentry->pending = FALSE;\n\tentry->error = error;\n\n\t/*\n\t * if the wait_pending flag is set, one or more threads may be waiting\n\t * on this buffer\n\t */\n\tif (entry->cache->wait_pending) {\n\t\tentry->cache->wait_pending = FALSE;\n\t\tpthread_cond_broadcast(&entry->cache->wait_for_pending);\n\t}\n\n\tpthread_mutex_unlock(&entry->cache->mutex);\n}\n\nvoid cache_block_wait(struct cache_entry *entry) {\n\t/*\n\t * wait for this cache entry to become ready, when reading and (if\n\t * necessary) decompression has taken place\n\t */\n\tpthread_mutex_lock(&entry->cache->mutex);\n\n\twhile (entry->pending) {\n\t\tentry->cache->wait_pending = TRUE;\n\t\tpthread_cond_wait(&entry->cache->wait_for_pending, &entry->cache->mutex);\n\t}\n\n\tpthread_mutex_unlock(&entry->cache->mutex);\n}\n\nvoid cache_block_put(struct cache_entry *entry) {\n\t/*\n\t * finished with this cache entry, once the usage count reaches zero it\n\t * can be reused and is put onto the free list.  As it remains\n\t * accessible via the hash table it can be found getting a new lease of\n\t * life before it is reused.\n\t */\n\tpthread_mutex_lock(&entry->cache->mutex);\n\n\tentry->used--;\n\tif (entry->used == 0) {\n\t\tinsert_free_list(entry->cache, entry);\n\t\tentry->cache->used--;\n\n\t\t/*\n\t\t * if the wait_free flag is set, one or more threads may be\n\t\t * waiting on this buffer\n\t\t */\n\t\tif (entry->cache->wait_free) {\n\t\t\tentry->cache->wait_free = FALSE;\n\t\t\tpthread_cond_broadcast(&entry->cache->wait_for_free);\n\t\t}\n\t}\n\n\tpthread_mutex_unlock(&entry->cache->mutex);\n}\n\nvoid dump_cache(struct cache *cache) {\n\tpthread_mutex_lock(&cache->mutex);\n\n\tprintf(\"Max buffers %d, Current size %d, Used %d,  %s\\n\", cache->max_buffers, cache->count, cache->used, cache->free_list ? \"Free buffers\" : \"No free buffers\");\n\n\tpthread_mutex_unlock(&cache->mutex);\n}\n\nchar *modestr(char *str, int mode) {\n\tint i;\n\n\tstrcpy(str, \"----------\");\n\n\tfor (i = 0; table[i].mask != 0; i++) {\n\t\tif ((mode & table[i].mask) == table[i].value)\n\t\t\tstr[table[i].position] = table[i].mode;\n\t}\n\n\treturn str;\n}\n\n#define TOTALCHARS  25\nint print_filename(char *pathname, struct inode *inode) {\n\tchar str[11], dummy[12], dummy2[12];\t/* overflow safe */\n\tchar *userstr, *groupstr;\n\tint padchars;\n\tstruct passwd *user;\n\tstruct group *group;\n\tstruct tm *t;\n\n\tif (short_ls) {\n\t\tprintf(\"%s\\n\", pathname);\n\t\treturn 1;\n\t}\n\n\tuser = getpwuid(inode->uid);\n\tif (user == NULL) {\n\t\tint res = snprintf(dummy, 12, \"%d\", inode->uid);\n\t\tif (res < 0)\n\t\t\tEXIT_UNSQUASH(\"snprintf failed in print_filename()\\n\");\n\t\telse if (res >= 12)\n\t\t\t/* unsigned int shouldn't ever need more than 11 bytes\n\t\t\t * (including terminating '\\0') to print in base 10 */\n\t\t\tuserstr = \"*\";\n\t\telse\n\t\t\tuserstr = dummy;\n\t} else\n\t\tuserstr = user->pw_name;\n\n\tgroup = getgrgid(inode->gid);\n\tif (group == NULL) {\n\t\tint res = snprintf(dummy2, 12, \"%d\", inode->gid);\n\t\tif (res < 0)\n\t\t\tEXIT_UNSQUASH(\"snprintf failed in print_filename()\\n\");\n\t\telse if (res >= 12)\n\t\t\t/* unsigned int shouldn't ever need more than 11 bytes\n\t\t\t * (including terminating '\\0') to print in base 10 */\n\t\t\tgroupstr = \"*\";\n\t\telse\n\t\t\tgroupstr = dummy2;\n\t} else\n\t\tgroupstr = group->gr_name;\n\n\tprintf(\"%s %s/%s \", modestr(str, inode->mode), userstr, groupstr);\n\n\tswitch (inode->mode & S_IFMT) {\n\tcase S_IFREG:\n\tcase S_IFDIR:\n\tcase S_IFSOCK:\n\tcase S_IFIFO:\n\tcase S_IFLNK:\n\t\tpadchars = TOTALCHARS - strlen(userstr) - strlen(groupstr);\n\n\t\tprintf(\"%*lld \", padchars > 0 ? padchars : 0, inode->data);\n\t\tbreak;\n\tcase S_IFCHR:\n\tcase S_IFBLK:\n\t\tpadchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7;\n\n\t\tprintf(\"%*s%3d,%3d \", padchars > 0 ? padchars : 0, \" \", (int)inode->data >> 8, (int)inode->data & 0xff);\n\t\tbreak;\n\t}\n\n\tt = localtime(&inode->time);\n\n\tprintf(\"%d-%02d-%02d %02d:%02d %s\", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname);\n\tif ((inode->mode & S_IFMT) == S_IFLNK)\n\t\tprintf(\" -> %s\", inode->symlink);\n\tprintf(\"\\n\");\n\n\treturn 1;\n}\n\nvoid add_entry(struct hash_table_entry *hash_table[], long long start, int bytes) {\n\tint hash = CALCULATE_HASH(start);\n\tstruct hash_table_entry *hash_table_entry;\n\n\thash_table_entry = malloc(sizeof(struct hash_table_entry));\n\tif (hash_table_entry == NULL)\n\t\tEXIT_UNSQUASH(\"Out of memory in add_entry\\n\");\n\n\thash_table_entry->start = start;\n\thash_table_entry->bytes = bytes;\n\thash_table_entry->next = hash_table[hash];\n\thash_table[hash] = hash_table_entry;\n}\n\nint lookup_entry(struct hash_table_entry *hash_table[], long long start) {\n\tint hash = CALCULATE_HASH(start);\n\tstruct hash_table_entry *hash_table_entry;\n\n\tfor (hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next)\n\n\t\tif (hash_table_entry->start == start)\n\t\t\treturn hash_table_entry->bytes;\n\n\treturn -1;\n}\n\nint read_fs_bytes(int fd, long long byte, int bytes, void *buff) {\n\toff_t off = byte;\n\tint res, count;\n\n\tTRACE(\"read_bytes: reading from position 0x%llx, bytes %d\\n\", byte, bytes);\n\n\tif (lseek(fd, off, SEEK_SET) == -1) {\n\t\tERROR(\"Lseek failed because %s\\n\", strerror(errno));\n\t\treturn FALSE;\n\t}\n\n\tfor (count = 0; count < bytes; count += res) {\n\t\tres = read(fd, buff + count, bytes - count);\n\t\tif (res < 1) {\n\t\t\tif (res == 0) {\n\t\t\t\tERROR(\"Read on filesystem failed because \" \"EOF\\n\");\n\t\t\t\treturn FALSE;\n\t\t\t} else if (errno != EINTR) {\n\t\t\t\tERROR(\"Read on filesystem failed because %s\\n\", strerror(errno));\n\t\t\t\treturn FALSE;\n\t\t\t} else\n\t\t\t\tres = 0;\n\t\t}\n\t}\n\n\treturn TRUE;\n}\n\nint read_block(int fd, long long start, long long *next, int expected, void *block) {\n\tunsigned short c_byte;\n\tint offset = 2, res, compressed;\n\tint outlen = expected ? expected : SQUASHFS_METADATA_SIZE;\n\n\tif (swap) {\n\t\tif (read_fs_bytes(fd, start, 2, &c_byte) == FALSE)\n\t\t\tgoto failed;\n\t\tc_byte = (c_byte >> 8) | ((c_byte & 0xff) << 8);\n\t} else if (read_fs_bytes(fd, start, 2, &c_byte) == FALSE)\n\t\tgoto failed;\n\n\tTRACE(\"read_block: block @0x%llx, %d %s bytes\\n\", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? \"compressed\" : \"uncompressed\");\n\n\tif (SQUASHFS_CHECK_DATA(sBlk.s.flags))\n\t\toffset = 3;\n\n\tcompressed = SQUASHFS_COMPRESSED(c_byte);\n\tc_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);\n\n\t/*\n\t * The block size should not be larger than\n\t * the uncompressed size (or max uncompressed size if\n\t * expected is 0)\n\t */\n\tif (c_byte > outlen)\n\t\treturn 0;\n\n\tif (compressed) {\n\t\tchar buffer[c_byte];\n\t\tint error;\n\n\t\tres = read_fs_bytes(fd, start + offset, c_byte, buffer);\n\t\tif (res == FALSE)\n\t\t\tgoto failed;\n\n\t\tres = compressor_uncompress(comp, block, buffer, c_byte, outlen, &error);\n\n\t\tif (res == -1) {\n\t\t\tERROR(\"%s uncompress failed with error code %d\\n\", comp->name, error);\n\t\t\tgoto failed;\n\t\t}\n\t} else {\n\t\tres = read_fs_bytes(fd, start + offset, c_byte, block);\n\t\tif (res == FALSE)\n\t\t\tgoto failed;\n\t\tres = c_byte;\n\t}\n\n\tif (next)\n\t\t*next = start + offset + c_byte;\n\n\t/*\n\t * if expected, then check the (uncompressed) return data\n\t * is of the expected size\n\t */\n\tif (expected && expected != res)\n\t\treturn 0;\n\telse\n\t\treturn res;\n\n failed:\n\tERROR(\"read_block: failed to read block @0x%llx\\n\", start);\n\treturn FALSE;\n}\n\nint read_data_block(long long start, unsigned int size, char *block) {\n\tint error, res;\n\tint c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size);\n\n\tTRACE(\"read_data_block: block @0x%llx, %d %s bytes\\n\", start, c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? \"compressed\" : \"uncompressed\");\n\n\tif (SQUASHFS_COMPRESSED_BLOCK(size)) {\n\t\tif (read_fs_bytes(fd, start, c_byte, data) == FALSE)\n\t\t\tgoto failed;\n\n\t\tres = compressor_uncompress(comp, block, data, c_byte, block_size, &error);\n\n\t\tif (res == -1) {\n\t\t\tERROR(\"%s uncompress failed with error code %d\\n\", comp->name, error);\n\t\t\tgoto failed;\n\t\t}\n\n\t\treturn res;\n\t} else {\n\t\tif (read_fs_bytes(fd, start, c_byte, block) == FALSE)\n\t\t\tgoto failed;\n\n\t\treturn c_byte;\n\t}\n\n failed:\n\tERROR(\"read_data_block: failed to read block @0x%llx, size %d\\n\", start, c_byte);\n\treturn FALSE;\n}\n\nint read_inode_table(long long start, long long end) {\n\tint size = 0, bytes = 0, res;\n\n\tTRACE(\"read_inode_table: start %lld, end %lld\\n\", start, end);\n\n\twhile (start < end) {\n\t\tif (size - bytes < SQUASHFS_METADATA_SIZE) {\n\t\t\tinode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE);\n\t\t\tif (inode_table == NULL) {\n\t\t\t\tERROR(\"Out of memory in read_inode_table\");\n\t\t\t\tgoto failed;\n\t\t\t}\n\t\t}\n\n\t\tadd_entry(inode_table_hash, start, bytes);\n\n\t\tres = read_block(fd, start, &start, 0, inode_table + bytes);\n\t\tif (res == 0) {\n\t\t\tERROR(\"read_inode_table: failed to read block\\n\");\n\t\t\tgoto failed;\n\t\t}\n\t\tbytes += res;\n\n\t\t/*\n\t\t * If this is not the last metadata block in the inode table\n\t\t * then it should be SQUASHFS_METADATA_SIZE in size.\n\t\t * Note, we can't use expected in read_block() above for this\n\t\t * because we don't know if this is the last block until\n\t\t * after reading.\n\t\t */\n\t\tif (start != end && res != SQUASHFS_METADATA_SIZE) {\n\t\t\tERROR(\"read_inode_table: metadata block should be %d \" \"bytes in length, it is %d bytes\\n\", SQUASHFS_METADATA_SIZE, res);\n\n\t\t\tgoto failed;\n\t\t}\n\t}\n\n\treturn TRUE;\n\n failed:\n\tfree(inode_table);\n\treturn FALSE;\n}\n\nint set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int xattr, unsigned int set_mode) {\n\tstruct utimbuf times = { time, time };\n\n\twrite_xattr(pathname, xattr);\n\n\tif (utime(pathname, &times) == -1) {\n\t\tERROR(\"set_attributes: failed to set time on %s, because %s\\n\", pathname, strerror(errno));\n\t\treturn FALSE;\n\t}\n\n\tif (root_process) {\n\t\tif (chown(pathname, uid, guid) == -1) {\n\t\t\tERROR(\"set_attributes: failed to change uid and gids \" \"on %s, because %s\\n\", pathname, strerror(errno));\n\t\t\treturn FALSE;\n\t\t}\n\t} else\n\t\tmode &= ~07000;\n\n\tif ((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) {\n\t\tERROR(\"set_attributes: failed to change mode %s, because %s\\n\", pathname, strerror(errno));\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\nint write_bytes(int fd, char *buff, int bytes) {\n\tint res, count;\n\n\tfor (count = 0; count < bytes; count += res) {\n\t\tres = write(fd, buff + count, bytes - count);\n\t\tif (res == -1) {\n\t\t\tif (errno != EINTR) {\n\t\t\t\tERROR(\"Write on output file failed because \" \"%s\\n\", strerror(errno));\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tres = 0;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint lseek_broken = FALSE;\nchar *zero_data = NULL;\n\nint write_block(int file_fd, char *buffer, int size, long long hole, int sparse) {\n\toff_t off = hole;\n\n\tif (hole) {\n\t\tif (sparse && lseek_broken == FALSE) {\n\t\t\tint error = lseek(file_fd, off, SEEK_CUR);\n\t\t\tif (error == -1)\n\t\t\t\t/* failed to seek beyond end of file */\n\t\t\t\tlseek_broken = TRUE;\n\t\t}\n\n\t\tif ((sparse == FALSE || lseek_broken) && zero_data == NULL) {\n\t\t\tif ((zero_data = malloc(block_size)) == NULL)\n\t\t\t\tEXIT_UNSQUASH(\"write_block: failed to alloc \" \"zero data block\\n\");\n\t\t\tmemset(zero_data, 0, block_size);\n\t\t}\n\n\t\tif (sparse == FALSE || lseek_broken) {\n\t\t\tint blocks = (hole + block_size - 1) / block_size;\n\t\t\tint avail_bytes, i;\n\t\t\tfor (i = 0; i < blocks; i++, hole -= avail_bytes) {\n\t\t\t\tavail_bytes = hole > block_size ? block_size : hole;\n\t\t\t\tif (write_bytes(file_fd, zero_data, avail_bytes)\n\t\t\t\t\t== -1)\n\t\t\t\t\tgoto failure;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (write_bytes(file_fd, buffer, size) == -1)\n\t\tgoto failure;\n\n\treturn TRUE;\n\n failure:\n\treturn FALSE;\n}\n\npthread_mutex_t open_mutex = PTHREAD_MUTEX_INITIALIZER;\npthread_cond_t open_empty = PTHREAD_COND_INITIALIZER;\nint open_unlimited, open_count;\n\nvoid open_init(int count) {\n\topen_count = count;\n\topen_unlimited = count == -1;\n}\n\nint open_wait(char *pathname, int flags, mode_t mode) {\n\tif (!open_unlimited) {\n\t\tpthread_mutex_lock(&open_mutex);\n\t\twhile (open_count == 0)\n\t\t\tpthread_cond_wait(&open_empty, &open_mutex);\n\t\topen_count--;\n\t\tpthread_mutex_unlock(&open_mutex);\n\t}\n\n\treturn open(pathname, flags, mode);\n}\n\nvoid close_wake(int fd) {\n\tclose(fd);\n\n\tif (!open_unlimited) {\n\t\tpthread_mutex_lock(&open_mutex);\n\t\topen_count++;\n\t\tpthread_cond_signal(&open_empty);\n\t\tpthread_mutex_unlock(&open_mutex);\n\t}\n}\n\nvoid queue_file(char *pathname, int file_fd, struct inode *inode) {\n\tstruct squashfs_file *file = malloc(sizeof(struct squashfs_file));\n\tif (file == NULL)\n\t\tEXIT_UNSQUASH(\"queue_file: unable to malloc file\\n\");\n\n\tfile->fd = file_fd;\n\tfile->file_size = inode->data;\n\tfile->mode = inode->mode;\n\tfile->gid = inode->gid;\n\tfile->uid = inode->uid;\n\tfile->time = inode->time;\n\tfile->pathname = strdup(pathname);\n\tfile->blocks = inode->blocks + (inode->frag_bytes > 0);\n\tfile->sparse = inode->sparse;\n\tfile->xattr = inode->xattr;\n\tqueue_put(to_writer, file);\n}\n\nvoid queue_dir(char *pathname, struct dir *dir) {\n\tstruct squashfs_file *file = malloc(sizeof(struct squashfs_file));\n\tif (file == NULL)\n\t\tEXIT_UNSQUASH(\"queue_dir: unable to malloc file\\n\");\n\n\tfile->fd = -1;\n\tfile->mode = dir->mode;\n\tfile->gid = dir->guid;\n\tfile->uid = dir->uid;\n\tfile->time = dir->mtime;\n\tfile->pathname = strdup(pathname);\n\tfile->xattr = dir->xattr;\n\tqueue_put(to_writer, file);\n}\n\nint write_file(struct inode *inode, char *pathname) {\n\tunsigned int file_fd, i;\n\tunsigned int *block_list;\n\tint file_end = inode->data / block_size;\n\tlong long start = inode->start;\n\n\tTRACE(\"write_file: regular file, blocks %d\\n\", inode->blocks);\n\n\tfile_fd = open_wait(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777);\n\tif (file_fd == -1) {\n\t\tERROR(\"write_file: failed to create file %s, because %s\\n\", pathname, strerror(errno));\n\t\treturn FALSE;\n\t}\n\n\tblock_list = malloc(inode->blocks * sizeof(unsigned int));\n\tif (block_list == NULL)\n\t\tEXIT_UNSQUASH(\"write_file: unable to malloc block list\\n\");\n\n\ts_ops.read_block_list(block_list, inode->block_ptr, inode->blocks);\n\n\t/*\n\t * the writer thread is queued a squashfs_file structure describing the\n\t * file.  If the file has one or more blocks or a fragment they are\n\t * queued separately (references to blocks in the cache).\n\t */\n\tqueue_file(pathname, file_fd, inode);\n\n\tfor (i = 0; i < inode->blocks; i++) {\n\t\tint c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]);\n\t\tstruct file_entry *block = malloc(sizeof(struct file_entry));\n\n\t\tif (block == NULL)\n\t\t\tEXIT_UNSQUASH(\"write_file: unable to malloc file\\n\");\n\t\tblock->offset = 0;\n\t\tblock->size = i == file_end ? inode->data & (block_size - 1) : block_size;\n\t\tif (block_list[i] == 0)\t/* sparse block */\n\t\t\tblock->buffer = NULL;\n\t\telse {\n\t\t\tblock->buffer = cache_get(data_cache, start, block_list[i]);\n\t\t\tstart += c_byte;\n\t\t}\n\t\tqueue_put(to_writer, block);\n\t}\n\n\tif (inode->frag_bytes) {\n\t\tint size;\n\t\tlong long start;\n\t\tstruct file_entry *block = malloc(sizeof(struct file_entry));\n\n\t\tif (block == NULL)\n\t\t\tEXIT_UNSQUASH(\"write_file: unable to malloc file\\n\");\n\t\ts_ops.read_fragment(inode->fragment, &start, &size);\n\t\tblock->buffer = cache_get(fragment_cache, start, size);\n\t\tblock->offset = inode->offset;\n\t\tblock->size = inode->frag_bytes;\n\t\tqueue_put(to_writer, block);\n\t}\n\n\tfree(block_list);\n\treturn TRUE;\n}\n\nint create_inode(char *pathname, struct inode *i) {\n\tTRACE(\"create_inode: pathname %s\\n\", pathname);\n\n\tif (created_inode[i->inode_number - 1]) {\n\t\tTRACE(\"create_inode: hard link\\n\");\n\t\tif (force)\n\t\t\tunlink(pathname);\n\n\t\tif (link(created_inode[i->inode_number - 1], pathname) == -1) {\n\t\t\tERROR(\"create_inode: failed to create hardlink, \" \"because %s\\n\", strerror(errno));\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\tswitch (i->type) {\n\tcase SQUASHFS_FILE_TYPE:\n\tcase SQUASHFS_LREG_TYPE:\n\t\tTRACE(\"create_inode: regular file, file_size %lld, \" \"blocks %d\\n\", i->data, i->blocks);\n\n\t\tif (write_file(i, pathname))\n\t\t\tfile_count++;\n\t\tbreak;\n\tcase SQUASHFS_SYMLINK_TYPE:\n\tcase SQUASHFS_LSYMLINK_TYPE:\n\t\tTRACE(\"create_inode: symlink, symlink_size %lld\\n\", i->data);\n\n\t\tif (force)\n\t\t\tunlink(pathname);\n\n\t\tif (symlink(i->symlink, pathname) == -1) {\n\t\t\tERROR(\"create_inode: failed to create symlink \" \"%s, because %s\\n\", pathname, strerror(errno));\n\t\t\tbreak;\n\t\t}\n\n\t\twrite_xattr(pathname, i->xattr);\n\n\t\tif (root_process) {\n\t\t\tif (lchown(pathname, i->uid, i->gid) == -1)\n\t\t\t\tERROR(\"create_inode: failed to change \" \"uid and gids on %s, because \" \"%s\\n\", pathname, strerror(errno));\n\t\t}\n\n\t\tsym_count++;\n\t\tbreak;\n\tcase SQUASHFS_BLKDEV_TYPE:\n\tcase SQUASHFS_CHRDEV_TYPE:\n\tcase SQUASHFS_LBLKDEV_TYPE:\n\tcase SQUASHFS_LCHRDEV_TYPE:{\n\t\t\tint chrdev = i->type == SQUASHFS_CHRDEV_TYPE;\n\t\t\tTRACE(\"create_inode: dev, rdev 0x%llx\\n\", i->data);\n\n\t\t\tif (root_process) {\n\t\t\t\tif (force)\n\t\t\t\t\tunlink(pathname);\n\n\t\t\t\tif (mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) {\n\t\t\t\t\tERROR(\"create_inode: failed to create \" \"%s device %s, because %s\\n\", chrdev ? \"character\" : \"block\", pathname, strerror(errno));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tset_attributes(pathname, i->mode, i->uid, i->gid, i->time, i->xattr, TRUE);\n\t\t\t\tdev_count++;\n\t\t\t} else\n\t\t\t\tERROR(\"create_inode: could not create %s \" \"device %s, because you're not \" \"superuser!\\n\", chrdev ? \"character\" : \"block\", pathname);\n\t\t\tbreak;\n\t\t}\n\tcase SQUASHFS_FIFO_TYPE:\n\tcase SQUASHFS_LFIFO_TYPE:\n\t\tTRACE(\"create_inode: fifo\\n\");\n\n\t\tif (force)\n\t\t\tunlink(pathname);\n\n\t\tif (mknod(pathname, S_IFIFO, 0) == -1) {\n\t\t\tERROR(\"create_inode: failed to create fifo %s, \" \"because %s\\n\", pathname, strerror(errno));\n\t\t\tbreak;\n\t\t}\n\t\tset_attributes(pathname, i->mode, i->uid, i->gid, i->time, i->xattr, TRUE);\n\t\tfifo_count++;\n\t\tbreak;\n\tcase SQUASHFS_SOCKET_TYPE:\n\tcase SQUASHFS_LSOCKET_TYPE:\n\t\tTRACE(\"create_inode: socket\\n\");\n\t\tERROR(\"create_inode: socket %s ignored\\n\", pathname);\n\t\tbreak;\n\tdefault:\n\t\tERROR(\"Unknown inode type %d in create_inode_table!\\n\", i->type);\n\t\treturn FALSE;\n\t}\n\n\tcreated_inode[i->inode_number - 1] = strdup(pathname);\n\n\treturn TRUE;\n}\n\nint read_directory_table(long long start, long long end) {\n\tint bytes = 0, size = 0, res;\n\n\tTRACE(\"read_directory_table: start %lld, end %lld\\n\", start, end);\n\n\twhile (start < end) {\n\t\tif (size - bytes < SQUASHFS_METADATA_SIZE) {\n\t\t\tdirectory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE);\n\t\t\tif (directory_table == NULL) {\n\t\t\t\tERROR(\"Out of memory in \" \"read_directory_table\\n\");\n\t\t\t\tgoto failed;\n\t\t\t}\n\t\t}\n\n\t\tadd_entry(directory_table_hash, start, bytes);\n\n\t\tres = read_block(fd, start, &start, 0, directory_table + bytes);\n\t\tif (res == 0) {\n\t\t\tERROR(\"read_directory_table: failed to read block\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\tbytes += res;\n\n\t\t/*\n\t\t * If this is not the last metadata block in the directory table\n\t\t * then it should be SQUASHFS_METADATA_SIZE in size.\n\t\t * Note, we can't use expected in read_block() above for this\n\t\t * because we don't know if this is the last block until\n\t\t * after reading.\n\t\t */\n\t\tif (start != end && res != SQUASHFS_METADATA_SIZE) {\n\t\t\tERROR(\"read_directory_table: metadata block \" \"should be %d bytes in length, it is %d \" \"bytes\\n\", SQUASHFS_METADATA_SIZE, res);\n\t\t\tgoto failed;\n\t\t}\n\t}\n\n\treturn TRUE;\n\n failed:\n\tfree(directory_table);\n\treturn FALSE;\n}\n\nint squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) {\n\tif (dir->cur_entry == dir->dir_count)\n\t\treturn FALSE;\n\n\t*name = dir->dirs[dir->cur_entry].name;\n\t*start_block = dir->dirs[dir->cur_entry].start_block;\n\t*offset = dir->dirs[dir->cur_entry].offset;\n\t*type = dir->dirs[dir->cur_entry].type;\n\tdir->cur_entry++;\n\n\treturn TRUE;\n}\n\nvoid squashfs_closedir(struct dir *dir) {\n\tfree(dir->dirs);\n\tfree(dir);\n}\n\nchar *get_component(char *target, char **targname) {\n\tchar *start;\n\n\twhile (*target == '/')\n\t\ttarget++;\n\n\tstart = target;\n\twhile (*target != '/' && *target != '\\0')\n\t\ttarget++;\n\n\t*targname = strndup(start, target - start);\n\n\twhile (*target == '/')\n\t\ttarget++;\n\n\treturn target;\n}\n\nvoid free_path(struct pathname *paths) {\n\tint i;\n\n\tfor (i = 0; i < paths->names; i++) {\n\t\tif (paths->name[i].paths)\n\t\t\tfree_path(paths->name[i].paths);\n\t\tfree(paths->name[i].name);\n\t\tif (paths->name[i].preg) {\n\t\t\tregfree(paths->name[i].preg);\n\t\t\tfree(paths->name[i].preg);\n\t\t}\n\t}\n\n\tfree(paths);\n}\n\nstruct pathname *add_path(struct pathname *paths, char *target, char *alltarget) {\n\tchar *targname;\n\tint i, error;\n\n\tTRACE(\"add_path: adding \\\"%s\\\" extract file\\n\", target);\n\n\ttarget = get_component(target, &targname);\n\n\tif (paths == NULL) {\n\t\tpaths = malloc(sizeof(struct pathname));\n\t\tif (paths == NULL)\n\t\t\tEXIT_UNSQUASH(\"failed to allocate paths\\n\");\n\n\t\tpaths->names = 0;\n\t\tpaths->name = NULL;\n\t}\n\n\tfor (i = 0; i < paths->names; i++)\n\t\tif (strcmp(paths->name[i].name, targname) == 0)\n\t\t\tbreak;\n\n\tif (i == paths->names) {\n\t\t/*\n\t\t * allocate new name entry\n\t\t */\n\t\tpaths->names++;\n\t\tpaths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry));\n\t\tif (paths->name == NULL)\n\t\t\tEXIT_UNSQUASH(\"Out of memory in add_path\\n\");\n\t\tpaths->name[i].name = targname;\n\t\tpaths->name[i].paths = NULL;\n\t\tif (use_regex) {\n\t\t\tpaths->name[i].preg = malloc(sizeof(regex_t));\n\t\t\tif (paths->name[i].preg == NULL)\n\t\t\t\tEXIT_UNSQUASH(\"Out of memory in add_path\\n\");\n\t\t\terror = regcomp(paths->name[i].preg, targname, REG_EXTENDED | REG_NOSUB);\n\t\t\tif (error) {\n\t\t\t\tchar str[1024];\t/* overflow safe */\n\n\t\t\t\tregerror(error, paths->name[i].preg, str, 1024);\n\t\t\t\tEXIT_UNSQUASH(\"invalid regex %s in export %s, \" \"because %s\\n\", targname, alltarget, str);\n\t\t\t}\n\t\t} else\n\t\t\tpaths->name[i].preg = NULL;\n\n\t\tif (target[0] == '\\0')\n\t\t\t/*\n\t\t\t * at leaf pathname component\n\t\t\t */\n\t\t\tpaths->name[i].paths = NULL;\n\t\telse\n\t\t\t/*\n\t\t\t * recurse adding child components\n\t\t\t */\n\t\t\tpaths->name[i].paths = add_path(NULL, target, alltarget);\n\t} else {\n\t\t/*\n\t\t * existing matching entry\n\t\t */\n\t\tfree(targname);\n\n\t\tif (paths->name[i].paths == NULL) {\n\t\t\t/*\n\t\t\t * No sub-directory which means this is the leaf\n\t\t\t * component of a pre-existing extract which subsumes\n\t\t\t * the extract currently being added, in which case stop\n\t\t\t * adding components\n\t\t\t */\n\t\t} else if (target[0] == '\\0') {\n\t\t\t/*\n\t\t\t * at leaf pathname component and child components exist\n\t\t\t * from more specific extracts, delete as they're\n\t\t\t * subsumed by this extract\n\t\t\t */\n\t\t\tfree_path(paths->name[i].paths);\n\t\t\tpaths->name[i].paths = NULL;\n\t\t} else\n\t\t\t/*\n\t\t\t * recurse adding child components\n\t\t\t */\n\t\t\tadd_path(paths->name[i].paths, target, alltarget);\n\t}\n\n\treturn paths;\n}\n\nstruct pathnames *init_subdir() {\n\tstruct pathnames *new = malloc(sizeof(struct pathnames));\n\tif (new == NULL)\n\t\tEXIT_UNSQUASH(\"Out of memory in init_subdir\\n\");\n\tnew->count = 0;\n\treturn new;\n}\n\nstruct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) {\n\tif (paths->count % PATHS_ALLOC_SIZE == 0) {\n\t\tpaths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *));\n\t\tif (paths == NULL)\n\t\t\tEXIT_UNSQUASH(\"Out of memory in add_subdir\\n\");\n\t}\n\n\tpaths->path[paths->count++] = path;\n\treturn paths;\n}\n\nvoid free_subdir(struct pathnames *paths) {\n\tfree(paths);\n}\n\nint matches(struct pathnames *paths, char *name, struct pathnames **new) {\n\tint i, n;\n\n\tif (paths == NULL) {\n\t\t*new = NULL;\n\t\treturn TRUE;\n\t}\n\n\t*new = init_subdir();\n\n\tfor (n = 0; n < paths->count; n++) {\n\t\tstruct pathname *path = paths->path[n];\n\t\tfor (i = 0; i < path->names; i++) {\n\t\t\tint match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0,\n\t\t\t\t\t\t\t\t\t\t\tNULL, 0) == 0 : fnmatch(path->name[i].name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tname, FNM_PATHNAME | FNM_PERIOD | FNM_EXTMATCH) == 0;\n\t\t\tif (match && path->name[i].paths == NULL)\n\t\t\t\t/*\n\t\t\t\t * match on a leaf component, any subdirectories\n\t\t\t\t * will implicitly match, therefore return an\n\t\t\t\t * empty new search set\n\t\t\t\t */\n\t\t\t\tgoto empty_set;\n\n\t\t\tif (match)\n\t\t\t\t/*\n\t\t\t\t * match on a non-leaf component, add any\n\t\t\t\t * subdirectories to the new set of\n\t\t\t\t * subdirectories to scan for this name\n\t\t\t\t */\n\t\t\t\t*new = add_subdir(*new, path->name[i].paths);\n\t\t}\n\t}\n\n\tif ((*new)->count == 0) {\n\t\t/*\n\t\t * no matching names found, delete empty search set, and return\n\t\t * FALSE\n\t\t */\n\t\tfree_subdir(*new);\n\t\t*new = NULL;\n\t\treturn FALSE;\n\t}\n\n\t/*\n\t * one or more matches with sub-directories found (no leaf matches),\n\t * return new search set and return TRUE\n\t */\n\treturn TRUE;\n\n empty_set:\n\t/*\n\t * found matching leaf exclude, return empty search set and return TRUE\n\t */\n\tfree_subdir(*new);\n\t*new = NULL;\n\treturn TRUE;\n}\n\nvoid pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) {\n\tunsigned int type;\n\tchar *name;\n\tstruct pathnames *new;\n\tstruct inode *i;\n\tstruct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i);\n\n\tif (dir == NULL)\n\t\treturn;\n\n\twhile (squashfs_readdir(dir, &name, &start_block, &offset, &type)) {\n\t\tstruct inode *i;\n\t\tchar *pathname;\n\t\tint res;\n\n\t\tTRACE(\"pre_scan: name %s, start_block %d, offset %d, type %d\\n\", name, start_block, offset, type);\n\n\t\tif (!matches(paths, name, &new))\n\t\t\tcontinue;\n\n\t\tres = asprintf(&pathname, \"%s/%s\", parent_name, name);\n\t\tif (res == -1)\n\t\t\tEXIT_UNSQUASH(\"asprintf failed in dir_scan\\n\");\n\n\t\tif (type == SQUASHFS_DIR_TYPE)\n\t\t\tpre_scan(parent_name, start_block, offset, new);\n\t\telse if (new == NULL) {\n\t\t\tif (type == SQUASHFS_FILE_TYPE || type == SQUASHFS_LREG_TYPE) {\n\t\t\t\ti = s_ops.read_inode(start_block, offset);\n\t\t\t\tif (created_inode[i->inode_number - 1] == NULL) {\n\t\t\t\t\tcreated_inode[i->inode_number - 1] = (char *)i;\n\t\t\t\t\ttotal_blocks += (i->data + (block_size - 1)) >> block_log;\n\t\t\t\t}\n\t\t\t\ttotal_files++;\n\t\t\t}\n\t\t\ttotal_inodes++;\n\t\t}\n\n\t\tfree_subdir(new);\n\t\tfree(pathname);\n\t}\n\n\tsquashfs_closedir(dir);\n}\n\nvoid dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) {\n\tunsigned int type;\n\tchar *name;\n\tstruct pathnames *new;\n\tstruct inode *i;\n\tstruct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i);\n\n\tif (dir == NULL) {\n\t\tERROR(\"dir_scan: failed to read directory %s, skipping\\n\", parent_name);\n\t\treturn;\n\t}\n\n\tif (lsonly || info)\n\t\tprint_filename(parent_name, i);\n\n\tif (!lsonly) {\n\t\t/*\n\t\t * Make directory with default User rwx permissions rather than\n\t\t * the permissions from the filesystem, as these may not have\n\t\t * write/execute permission.  These are fixed up later in\n\t\t * set_attributes().\n\t\t */\n\t\tint res = mkdir(parent_name, S_IRUSR | S_IWUSR | S_IXUSR);\n\t\tif (res == -1) {\n\t\t\t/*\n\t\t\t * Skip directory if mkdir fails, unless we're\n\t\t\t * forcing and the error is -EEXIST\n\t\t\t */\n\t\t\tif (!force || errno != EEXIST) {\n\t\t\t\tERROR(\"dir_scan: failed to make directory %s, \" \"because %s\\n\", parent_name, strerror(errno));\n\t\t\t\tsquashfs_closedir(dir);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Try to change permissions of existing directory so\n\t\t\t * that we can write to it\n\t\t\t */\n\t\t\tres = chmod(parent_name, S_IRUSR | S_IWUSR | S_IXUSR);\n\t\t\tif (res == -1)\n\t\t\t\tERROR(\"dir_scan: failed to change permissions \" \"for directory %s, because %s\\n\", parent_name, strerror(errno));\n\t\t}\n\t}\n\n\twhile (squashfs_readdir(dir, &name, &start_block, &offset, &type)) {\n\t\tchar *pathname;\n\t\tint res;\n\n\t\tTRACE(\"dir_scan: name %s, start_block %d, offset %d, type %d\\n\", name, start_block, offset, type);\n\n\t\tif (!matches(paths, name, &new))\n\t\t\tcontinue;\n\n\t\tres = asprintf(&pathname, \"%s/%s\", parent_name, name);\n\t\tif (res == -1)\n\t\t\tEXIT_UNSQUASH(\"asprintf failed in dir_scan\\n\");\n\n\t\tif (type == SQUASHFS_DIR_TYPE) {\n\t\t\tdir_scan(pathname, start_block, offset, new);\n\t\t\tfree(pathname);\n\t\t} else if (new == NULL) {\n\t\t\tupdate_info(pathname);\n\n\t\t\ti = s_ops.read_inode(start_block, offset);\n\n\t\t\tif (lsonly || info)\n\t\t\t\tprint_filename(pathname, i);\n\n\t\t\tif (!lsonly)\n\t\t\t\tcreate_inode(pathname, i);\n\n\t\t\tif (i->type == SQUASHFS_SYMLINK_TYPE || i->type == SQUASHFS_LSYMLINK_TYPE)\n\t\t\t\tfree(i->symlink);\n\t\t} else\n\t\t\tfree(pathname);\n\n\t\tfree_subdir(new);\n\t}\n\n\tif (!lsonly)\n\t\tqueue_dir(parent_name, dir);\n\n\tsquashfs_closedir(dir);\n\tdir_count++;\n}\n\nvoid squashfs_stat(char *source) {\n\ttime_t mkfs_time = (time_t) sBlk.s.mkfs_time;\n\tchar *mkfs_str = ctime(&mkfs_time);\n\n#if __BYTE_ORDER == __BIG_ENDIAN\n\tprintf(\"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);\n#else\n\tprintf(\"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);\n#endif\n\n\tprintf(\"Creation or last append time %s\", mkfs_str ? mkfs_str : \"failed to get time\\n\");\n\tprintf(\"Filesystem size %.2f Kbytes (%.2f Mbytes)\\n\", sBlk.s.bytes_used / 1024.0, sBlk.s.bytes_used / (1024.0 * 1024.0));\n\n\tif (sBlk.s.s_major == 4) {\n\t\tprintf(\"Compression %s\\n\", comp->name);\n\n\t\tif (SQUASHFS_COMP_OPTS(sBlk.s.flags)) {\n\t\t\tchar buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned));\n\t\t\tint bytes;\n\n\t\t\tbytes = read_block(fd, sizeof(sBlk.s), NULL, 0, buffer);\n\t\t\tif (bytes == 0) {\n\t\t\t\tERROR(\"Failed to read compressor options\\n\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcompressor_display_options(comp, buffer, bytes);\n\t\t}\n\t}\n\n\tprintf(\"Block size %d\\n\", sBlk.s.block_size);\n\tprintf(\"Filesystem is %sexportable via NFS\\n\", SQUASHFS_EXPORTABLE(sBlk.s.flags) ? \"\" : \"not \");\n\tprintf(\"Inodes are %scompressed\\n\", SQUASHFS_UNCOMPRESSED_INODES(sBlk.s.flags) ? \"un\" : \"\");\n\tprintf(\"Data is %scompressed\\n\", SQUASHFS_UNCOMPRESSED_DATA(sBlk.s.flags) ? \"un\" : \"\");\n\n\tif (sBlk.s.s_major > 1) {\n\t\tif (SQUASHFS_NO_FRAGMENTS(sBlk.s.flags))\n\t\t\tprintf(\"Fragments are not stored\\n\");\n\t\telse {\n\t\t\tprintf(\"Fragments are %scompressed\\n\", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.s.flags) ? \"un\" : \"\");\n\t\t\tprintf(\"Always-use-fragments option is %sspecified\\n\", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.s.flags) ? \"\" : \"not \");\n\t\t}\n\t}\n\n\tif (sBlk.s.s_major == 4) {\n\t\tif (SQUASHFS_NO_XATTRS(sBlk.s.flags))\n\t\t\tprintf(\"Xattrs are not stored\\n\");\n\t\telse\n\t\t\tprintf(\"Xattrs are %scompressed\\n\", SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.s.flags) ? \"un\" : \"\");\n\t}\n\n\tif (sBlk.s.s_major < 4)\n\t\tprintf(\"Check data is %spresent in the filesystem\\n\", SQUASHFS_CHECK_DATA(sBlk.s.flags) ? \"\" : \"not \");\n\n\tif (sBlk.s.s_major > 1)\n\t\tprintf(\"Duplicates are %sremoved\\n\", SQUASHFS_DUPLICATES(sBlk.s.flags) ? \"\" : \"not \");\n\telse\n\t\tprintf(\"Duplicates are removed\\n\");\n\n\tif (sBlk.s.s_major > 1)\n\t\tprintf(\"Number of fragments %d\\n\", sBlk.s.fragments);\n\n\tprintf(\"Number of inodes %d\\n\", sBlk.s.inodes);\n\n\tif (sBlk.s.s_major == 4)\n\t\tprintf(\"Number of ids %d\\n\", sBlk.s.no_ids);\n\telse {\n\t\tprintf(\"Number of uids %d\\n\", sBlk.no_uids);\n\t\tprintf(\"Number of gids %d\\n\", sBlk.no_guids);\n\t}\n\n\tTRACE(\"sBlk.s.inode_table_start 0x%llx\\n\", sBlk.s.inode_table_start);\n\tTRACE(\"sBlk.s.directory_table_start 0x%llx\\n\", sBlk.s.directory_table_start);\n\n\tif (sBlk.s.s_major > 1)\n\t\tTRACE(\"sBlk.s.fragment_table_start 0x%llx\\n\\n\", sBlk.s.fragment_table_start);\n\n\tif (sBlk.s.s_major > 2)\n\t\tTRACE(\"sBlk.s.lookup_table_start 0x%llx\\n\\n\", sBlk.s.lookup_table_start);\n\n\tif (sBlk.s.s_major == 4) {\n\t\tTRACE(\"sBlk.s.id_table_start 0x%llx\\n\", sBlk.s.id_table_start);\n\t\tTRACE(\"sBlk.s.xattr_id_table_start 0x%llx\\n\", sBlk.s.xattr_id_table_start);\n\t} else {\n\t\tTRACE(\"sBlk.uid_start 0x%llx\\n\", sBlk.uid_start);\n\t\tTRACE(\"sBlk.guid_start 0x%llx\\n\", sBlk.guid_start);\n\t}\n}\n\nint check_compression(struct compressor *comp) {\n\tint res, bytes = 0;\n\tchar buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned));\n\n\tif (!comp->supported) {\n\t\tERROR(\"Filesystem uses %s compression, this is \" \"unsupported by this version\\n\", comp->name);\n\t\tERROR(\"Decompressors available:\\n\");\n\t\tdisplay_compressors(\"\", \"\");\n\t\treturn 0;\n\t}\n\n\t/*\n\t * Read compression options from disk if present, and pass to\n\t * the compressor to ensure we know how to decompress a filesystem\n\t * compressed with these compression options.\n\t *\n\t * Note, even if there is no compression options we still call the\n\t * compressor because some compression options may be mandatory\n\t * for some compressors.\n\t */\n\tif (SQUASHFS_COMP_OPTS(sBlk.s.flags)) {\n\t\tbytes = read_block(fd, sizeof(sBlk.s), NULL, 0, buffer);\n\t\tif (bytes == 0) {\n\t\t\tERROR(\"Failed to read compressor options\\n\");\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tres = compressor_check_options(comp, sBlk.s.block_size, buffer, bytes);\n\n\treturn res != -1;\n}\n\nint read_super(char *source) {\n\tsquashfs_super_block_3 sBlk_3;\n\tstruct squashfs_super_block sBlk_4;\n\n\t/*\n\t * Try to read a Squashfs 4 superblock\n\t */\n\tread_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), &sBlk_4);\n\tswap = sBlk_4.s_magic != SQUASHFS_MAGIC;\n\tSQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4);\n\n\tif (sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 && sBlk_4.s_minor == 0) {\n\t\ts_ops.squashfs_opendir = squashfs_opendir_4;\n\t\ts_ops.read_fragment = read_fragment_4;\n\t\ts_ops.read_fragment_table = read_fragment_table_4;\n\t\ts_ops.read_block_list = read_block_list_2;\n\t\ts_ops.read_inode = read_inode_4;\n\t\ts_ops.read_uids_guids = read_uids_guids_4;\n\t\tmemcpy(&sBlk, &sBlk_4, sizeof(sBlk_4));\n\n\t\t/*\n\t\t * Check the compression type\n\t\t */\n\t\tcomp = lookup_compressor_id(sBlk.s.compression);\n\t\treturn TRUE;\n\t}\n\n\t/*\n\t * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock\n\t * (compatible with 1 and 2 filesystems)\n\t */\n\tread_fs_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block_3), &sBlk_3);\n\n\t/*\n\t * Check it is a SQUASHFS superblock\n\t */\n\tswap = 0;\n\tif (sBlk_3.s_magic != SQUASHFS_MAGIC) {\n\t\tif (sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) {\n\t\t\tsquashfs_super_block_3 sblk;\n\t\t\tERROR(\"Reading a different endian SQUASHFS filesystem \" \"on %s\\n\", source);\n\t\t\tSQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3);\n\t\t\tmemcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3));\n\t\t\tswap = 1;\n\t\t} else {\n\t\t\t//ERROR(\"Can't find a SQUASHFS superblock on %s\\n\", source);\n\t\t\tgoto failed_mount;\n\t\t}\n\t}\n\n\tsBlk.s.s_magic = sBlk_3.s_magic;\n\tsBlk.s.inodes = sBlk_3.inodes;\n\tsBlk.s.mkfs_time = sBlk_3.mkfs_time;\n\tsBlk.s.block_size = sBlk_3.block_size;\n\tsBlk.s.fragments = sBlk_3.fragments;\n\tsBlk.s.block_log = sBlk_3.block_log;\n\tsBlk.s.flags = sBlk_3.flags;\n\tsBlk.s.s_major = sBlk_3.s_major;\n\tsBlk.s.s_minor = sBlk_3.s_minor;\n\tsBlk.s.root_inode = sBlk_3.root_inode;\n\tsBlk.s.bytes_used = sBlk_3.bytes_used;\n\tsBlk.s.inode_table_start = sBlk_3.inode_table_start;\n\tsBlk.s.directory_table_start = sBlk_3.directory_table_start;\n\tsBlk.s.fragment_table_start = sBlk_3.fragment_table_start;\n\tsBlk.s.lookup_table_start = sBlk_3.lookup_table_start;\n\tsBlk.no_uids = sBlk_3.no_uids;\n\tsBlk.no_guids = sBlk_3.no_guids;\n\tsBlk.uid_start = sBlk_3.uid_start;\n\tsBlk.guid_start = sBlk_3.guid_start;\n\tsBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK;\n\n\t/* Check the MAJOR & MINOR versions */\n\tif (sBlk.s.s_major == 1 || sBlk.s.s_major == 2) {\n\t\tsBlk.s.bytes_used = sBlk_3.bytes_used_2;\n\t\tsBlk.uid_start = sBlk_3.uid_start_2;\n\t\tsBlk.guid_start = sBlk_3.guid_start_2;\n\t\tsBlk.s.inode_table_start = sBlk_3.inode_table_start_2;\n\t\tsBlk.s.directory_table_start = sBlk_3.directory_table_start_2;\n\n\t\tif (sBlk.s.s_major == 1) {\n\t\t\tsBlk.s.block_size = sBlk_3.block_size_1;\n\t\t\tsBlk.s.fragment_table_start = sBlk.uid_start;\n\t\t\ts_ops.squashfs_opendir = squashfs_opendir_1;\n\t\t\ts_ops.read_fragment_table = read_fragment_table_1;\n\t\t\ts_ops.read_block_list = read_block_list_1;\n\t\t\ts_ops.read_inode = read_inode_1;\n\t\t\ts_ops.read_uids_guids = read_uids_guids_1;\n\t\t} else {\n\t\t\tsBlk.s.fragment_table_start = sBlk_3.fragment_table_start_2;\n\t\t\ts_ops.squashfs_opendir = squashfs_opendir_1;\n\t\t\ts_ops.read_fragment = read_fragment_2;\n\t\t\ts_ops.read_fragment_table = read_fragment_table_2;\n\t\t\ts_ops.read_block_list = read_block_list_2;\n\t\t\ts_ops.read_inode = read_inode_2;\n\t\t\ts_ops.read_uids_guids = read_uids_guids_1;\n\t\t}\n\t} else if (sBlk.s.s_major == 3) {\n\t\ts_ops.squashfs_opendir = squashfs_opendir_3;\n\t\ts_ops.read_fragment = read_fragment_3;\n\t\ts_ops.read_fragment_table = read_fragment_table_3;\n\t\ts_ops.read_block_list = read_block_list_2;\n\t\ts_ops.read_inode = read_inode_3;\n\t\ts_ops.read_uids_guids = read_uids_guids_1;\n\t} else {\n\t\tERROR(\"Filesystem on %s is (%d:%d), \", source, sBlk.s.s_major, sBlk.s.s_minor);\n\t\tERROR(\"which is a later filesystem version than I support!\\n\");\n\t\tgoto failed_mount;\n\t}\n\n\t/*\n\t * 1.x, 2.x and 3.x filesystems use gzip compression.\n\t */\n\tcomp = lookup_compressor(\"gzip\");\n\treturn TRUE;\n\n failed_mount:\n\treturn FALSE;\n}\n\nstruct pathname *process_extract_files(struct pathname *path, char *filename) {\n\tFILE *fd;\n\tchar buffer[MAX_LINE + 1];\t/* overflow safe */\n\tchar *name;\n\n\tfd = fopen(filename, \"r\");\n\tif (fd == NULL)\n\t\tEXIT_UNSQUASH(\"Failed to open extract file \\\"%s\\\" because %s\\n\", filename, strerror(errno));\n\n\twhile (fgets(name = buffer, MAX_LINE + 1, fd) != NULL) {\n\t\tint len = strlen(name);\n\n\t\tif (len == MAX_LINE && name[len - 1] != '\\n')\n\t\t\t/* line too large */\n\t\t\tEXIT_UNSQUASH(\"Line too long when reading \" \"extract file \\\"%s\\\", larger than %d \" \"bytes\\n\", filename, MAX_LINE);\n\n\t\t/*\n\t\t * Remove '\\n' terminator if it exists (the last line\n\t\t * in the file may not be '\\n' terminated)\n\t\t */\n\t\tif (len && name[len - 1] == '\\n')\n\t\t\tname[len - 1] = '\\0';\n\n\t\t/* Skip any leading whitespace */\n\t\twhile (isspace(*name))\n\t\t\tname++;\n\n\t\t/* if comment line, skip */\n\t\tif (*name == '#')\n\t\t\tcontinue;\n\n\t\t/* check for initial backslash, to accommodate\n\t\t * filenames with leading space or leading # character\n\t\t */\n\t\tif (*name == '\\\\')\n\t\t\tname++;\n\n\t\t/* if line is now empty after skipping characters, skip it */\n\t\tif (*name == '\\0')\n\t\t\tcontinue;\n\n\t\tpath = add_path(path, name, name);\n\t}\n\n\tif (ferror(fd))\n\t\tEXIT_UNSQUASH(\"Reading extract file \\\"%s\\\" failed because %s\\n\", filename, strerror(errno));\n\n\tfclose(fd);\n\treturn path;\n}\n\n/*\n * reader thread.  This thread processes read requests queued by the\n * cache_get() routine.\n */\nvoid *reader(void *arg) {\n\twhile (1) {\n\t\tstruct cache_entry *entry = queue_get(to_reader);\n\t\tint res = read_fs_bytes(fd, entry->block,\n\t\t\t\t\t\t\t\tSQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size),\n\t\t\t\t\t\t\t\tentry->data);\n\n\t\tif (res && SQUASHFS_COMPRESSED_BLOCK(entry->size))\n\t\t\t/*\n\t\t\t * queue successfully read block to the inflate\n\t\t\t * thread(s) for further processing\n\t\t\t */\n\t\t\tqueue_put(to_inflate, entry);\n\t\telse\n\t\t\t/*\n\t\t\t * block has either been successfully read and is\n\t\t\t * uncompressed, or an error has occurred, clear pending\n\t\t\t * flag, set error appropriately, and wake up any\n\t\t\t * threads waiting on this buffer\n\t\t\t */\n\t\t\tcache_block_ready(entry, !res);\n\t}\n}\n\n/*\n * writer thread.  This processes file write requests queued by the\n * write_file() routine.\n */\nvoid *writer(void *arg) {\n\tint i;\n\n\twhile (1) {\n\t\tstruct squashfs_file *file = queue_get(to_writer);\n\t\tint file_fd;\n\t\tlong long hole = 0;\n\t\tint failed = FALSE;\n\t\tint error;\n\n\t\tif (file == NULL) {\n\t\t\tqueue_put(from_writer, NULL);\n\t\t\tcontinue;\n\t\t} else if (file->fd == -1) {\n\t\t\t/* write attributes for directory file->pathname */\n\t\t\tset_attributes(file->pathname, file->mode, file->uid, file->gid, file->time, file->xattr, TRUE);\n\t\t\tfree(file->pathname);\n\t\t\tfree(file);\n\t\t\tcontinue;\n\t\t}\n\n\t\tTRACE(\"writer: regular file, blocks %d\\n\", file->blocks);\n\n\t\tfile_fd = file->fd;\n\n\t\tfor (i = 0; i < file->blocks; i++, cur_blocks++) {\n\t\t\tstruct file_entry *block = queue_get(to_writer);\n\n\t\t\tif (block->buffer == 0) {\t/* sparse file */\n\t\t\t\thole += block->size;\n\t\t\t\tfree(block);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcache_block_wait(block->buffer);\n\n\t\t\tif (block->buffer->error)\n\t\t\t\tfailed = TRUE;\n\n\t\t\tif (failed)\n\t\t\t\tcontinue;\n\n\t\t\terror = write_block(file_fd, block->buffer->data + block->offset, block->size, hole, file->sparse);\n\n\t\t\tif (error == FALSE) {\n\t\t\t\tERROR(\"writer: failed to write data block %d\\n\", i);\n\t\t\t\tfailed = TRUE;\n\t\t\t}\n\n\t\t\thole = 0;\n\t\t\tcache_block_put(block->buffer);\n\t\t\tfree(block);\n\t\t}\n\n\t\tif (hole && failed == FALSE) {\n\t\t\t/*\n\t\t\t * corner case for hole extending to end of file\n\t\t\t */\n\t\t\tif (file->sparse == FALSE || lseek(file_fd, hole, SEEK_CUR) == -1) {\n\t\t\t\t/*\n\t\t\t\t * for files which we don't want to write\n\t\t\t\t * sparsely, or for broken lseeks which cannot\n\t\t\t\t * seek beyond end of file, write_block will do\n\t\t\t\t * the right thing\n\t\t\t\t */\n\t\t\t\thole--;\n\t\t\t\tif (write_block(file_fd, \"\\0\", 1, hole, file->sparse) == FALSE) {\n\t\t\t\t\tERROR(\"writer: failed to write sparse \" \"data block\\n\");\n\t\t\t\t\tfailed = TRUE;\n\t\t\t\t}\n\t\t\t} else if (ftruncate(file_fd, file->file_size) == -1) {\n\t\t\t\tERROR(\"writer: failed to write sparse data \" \"block\\n\");\n\t\t\t\tfailed = TRUE;\n\t\t\t}\n\t\t}\n\n\t\tclose_wake(file_fd);\n\t\tif (failed == FALSE)\n\t\t\tset_attributes(file->pathname, file->mode, file->uid, file->gid, file->time, file->xattr, force);\n\t\telse {\n\t\t\tERROR(\"Failed to write %s, skipping\\n\", file->pathname);\n\t\t\tunlink(file->pathname);\n\t\t}\n\t\tfree(file->pathname);\n\t\tfree(file);\n\n\t}\n}\n\n/*\n * decompress thread.  This decompresses buffers queued by the read thread\n */\nvoid *inflator(void *arg) {\n\tchar tmp[block_size];\n\n\twhile (1) {\n\t\tstruct cache_entry *entry = queue_get(to_inflate);\n\t\tint error, res;\n\n\t\tres = compressor_uncompress(comp, tmp, entry->data, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, &error);\n\n\t\tif (res == -1)\n\t\t\tERROR(\"%s uncompress failed with error code %d\\n\", comp->name, error);\n\t\telse\n\t\t\tmemcpy(entry->data, tmp, res);\n\n\t\t/*\n\t\t * block has been either successfully decompressed, or an error\n\t\t * occurred, clear pending flag, set error appropriately and\n\t\t * wake up any threads waiting on this block\n\t\t */\n\t\tcache_block_ready(entry, res == -1);\n\t}\n}\n\nvoid *progress_thread(void *arg) {\n\tstruct timespec requested_time, remaining;\n\tstruct itimerval itimerval;\n\tstruct winsize winsize;\n\n\tif (ioctl(1, TIOCGWINSZ, &winsize) == -1) {\n\t\tif (isatty(STDOUT_FILENO))\n\t\t\tERROR(\"TIOCGWINSZ ioctl failed, defaulting to 80 \" \"columns\\n\");\n\t\tcolumns = 80;\n\t} else\n\t\tcolumns = winsize.ws_col;\n\tsignal(SIGWINCH, sigwinch_handler);\n\tsignal(SIGALRM, sigalrm_handler);\n\n\titimerval.it_value.tv_sec = 0;\n\titimerval.it_value.tv_usec = 250000;\n\titimerval.it_interval.tv_sec = 0;\n\titimerval.it_interval.tv_usec = 250000;\n\tsetitimer(ITIMER_REAL, &itimerval, NULL);\n\n\trequested_time.tv_sec = 0;\n\trequested_time.tv_nsec = 250000000;\n\n\twhile (1) {\n\t\tint res = nanosleep(&requested_time, &remaining);\n\n\t\tif (res == -1 && errno != EINTR)\n\t\t\tEXIT_UNSQUASH(\"nanosleep failed in progress thread\\n\");\n\n\t\tif (progress_enabled) {\n\t\t\tpthread_mutex_lock(&screen_mutex);\n\t\t\tprogress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns);\n\t\t\tpthread_mutex_unlock(&screen_mutex);\n\t\t}\n\t}\n}\n\nvoid initialise_threads(int fragment_buffer_size, int data_buffer_size) {\n\tstruct rlimit rlim;\n\tint i, max_files, res;\n\tsigset_t sigmask, old_mask;\n\n\t/* block SIGQUIT and SIGHUP, these are handled by the info thread */\n\tsigemptyset(&sigmask);\n\tsigaddset(&sigmask, SIGQUIT);\n\tsigaddset(&sigmask, SIGHUP);\n\tif (pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == -1)\n\t\tEXIT_UNSQUASH(\"Failed to set signal mask in initialise_threads\" \"\\n\");\n\n\t/*\n\t * temporarily block these signals so the created sub-threads will\n\t * ignore them, ensuring the main thread handles them\n\t */\n\tsigemptyset(&sigmask);\n\tsigaddset(&sigmask, SIGINT);\n\tsigaddset(&sigmask, SIGTERM);\n\tif (pthread_sigmask(SIG_BLOCK, &sigmask, &old_mask) == -1)\n\t\tEXIT_UNSQUASH(\"Failed to set signal mask in initialise_threads\" \"\\n\");\n\n\tif (processors == -1) {\n#if !defined(linux) && !defined(__CYGWIN__)\n\t\tint mib[2];\n\t\tsize_t len = sizeof(processors);\n\n\t\tmib[0] = CTL_HW;\n#    ifdef HW_AVAILCPU\n\t\tmib[1] = HW_AVAILCPU;\n#    else\n\t\tmib[1] = HW_NCPU;\n#    endif\n\n\t\tif (sysctl(mib, 2, &processors, &len, NULL, 0) == -1) {\n\t\t\tERROR(\"Failed to get number of available processors.  \" \"Defaulting to 1\\n\");\n\t\t\tprocessors = 1;\n\t\t}\n#else\n\t\tprocessors = sysconf(_SC_NPROCESSORS_ONLN);\n#endif\n\t}\n\n\tif (add_overflow(processors, 3) || multiply_overflow(processors + 3, sizeof(pthread_t)))\n\t\tEXIT_UNSQUASH(\"Processors too large\\n\");\n\n\tthread = malloc((3 + processors) * sizeof(pthread_t));\n\tif (thread == NULL)\n\t\tEXIT_UNSQUASH(\"Out of memory allocating thread descriptors\\n\");\n\tinflator_thread = &thread[3];\n\n\t/*\n\t * dimensioning the to_reader and to_inflate queues.  The size of\n\t * these queues is directly related to the amount of block\n\t * read-ahead possible.  To_reader queues block read requests to\n\t * the reader thread and to_inflate queues block decompression\n\t * requests to the inflate thread(s) (once the block has been read by\n\t * the reader thread).  The amount of read-ahead is determined by\n\t * the combined size of the data_block and fragment caches which\n\t * determine the total number of blocks which can be \"in flight\"\n\t * at any one time (either being read or being decompressed)\n\t *\n\t * The maximum file open limit, however, affects the read-ahead\n\t * possible, in that for normal sizes of the fragment and data block\n\t * caches, where the incoming files have few data blocks or one fragment\n\t * only, the file open limit is likely to be reached before the\n\t * caches are full.  This means the worst case sizing of the combined\n\t * sizes of the caches is unlikely to ever be necessary.  However, is is\n\t * obvious read-ahead up to the data block cache size is always possible\n\t * irrespective of the file open limit, because a single file could\n\t * contain that number of blocks.\n\t *\n\t * Choosing the size as \"file open limit + data block cache size\" seems\n\t * to be a reasonable estimate.  We can reasonably assume the maximum\n\t * likely read-ahead possible is data block cache size + one fragment\n\t * per open file.\n\t *\n\t * dimensioning the to_writer queue.  The size of this queue is\n\t * directly related to the amount of block read-ahead possible.\n\t * However, unlike the to_reader and to_inflate queues, this is\n\t * complicated by the fact the to_writer queue not only contains\n\t * entries for fragments and data_blocks but it also contains\n\t * file entries, one per open file in the read-ahead.\n\t *\n\t * Choosing the size as \"2 * (file open limit) +\n\t * data block cache size\" seems to be a reasonable estimate.\n\t * We can reasonably assume the maximum likely read-ahead possible\n\t * is data block cache size + one fragment per open file, and then\n\t * we will have a file_entry for each open file.\n\t */\n\tres = getrlimit(RLIMIT_NOFILE, &rlim);\n\tif (res == -1) {\n\t\tERROR(\"failed to get open file limit!  Defaulting to 1\\n\");\n\t\trlim.rlim_cur = 1;\n\t}\n\n\tif (rlim.rlim_cur != RLIM_INFINITY) {\n\t\tmax_files = rlim.rlim_cur;\n\n\t\tstruct pollfd *fds = calloc(max_files, sizeof(struct pollfd));\n\t\tuint cur_file, opened_files = 0;\n\t\tfor(cur_file = 0; cur_file < max_files; cur_file++){\n\t\t\tfds[cur_file].fd = cur_file;\n\t\t}\n\t\tpoll(fds, max_files, 0);\n\t\tfor(cur_file = 0; cur_file < max_files; cur_file++){\n\t\t\tif(!(fds[cur_file].revents & POLLNVAL)){\n\t\t\t\topened_files++;\n\t\t\t}\n\t\t}\n\n\t\tif(opened_files > max_files){\n\t\t\tEXIT_UNSQUASH(\"Too many open files\");\n\t\t}\n\n\t\t// leave 10% of the free files free\n\t\tuint margin = (max_files - opened_files) / 10;\n\t\tmax_files -= margin;\n\n\t\tprintf(\"Max Files: %ju, Opened Files: %u, Allocated: %u (Margin: %u)\\n\",\n\t\t\t(uintmax_t) rlim.rlim_cur, opened_files, max_files, margin\n\t\t);\n\t\tfree(fds);\n\n\t} else\n\t\tmax_files = -1;\n\n\n\t/* set amount of available files for use by open_wait and close_wake */\n\topen_init(max_files);\n\n\t/*\n\t * allocate to_reader, to_inflate and to_writer queues.  Set based on\n\t * open file limit and cache size, unless open file limit is unlimited,\n\t * in which case set purely based on cache limits\n\t *\n\t * In doing so, check that the user supplied values do not overflow\n\t * a signed int\n\t */\n\tif (max_files != -1) {\n\t\tif (add_overflow(data_buffer_size, max_files) || add_overflow(data_buffer_size, max_files * 2))\n\t\t\tEXIT_UNSQUASH(\"Data queue size is too large\\n\");\n\n\t\tto_reader = queue_init(max_files + data_buffer_size);\n\t\tto_inflate = queue_init(max_files + data_buffer_size);\n\t\tto_writer = queue_init(max_files * 2 + data_buffer_size);\n\t} else {\n\t\tint all_buffers_size;\n\n\t\tif (add_overflow(fragment_buffer_size, data_buffer_size))\n\t\t\tEXIT_UNSQUASH(\"Data and fragment queues combined are\" \" too large\\n\");\n\n\t\tall_buffers_size = fragment_buffer_size + data_buffer_size;\n\n\t\tif (add_overflow(all_buffers_size, all_buffers_size))\n\t\t\tEXIT_UNSQUASH(\"Data and fragment queues combined are\" \" too large\\n\");\n\n\t\tto_reader = queue_init(all_buffers_size);\n\t\tto_inflate = queue_init(all_buffers_size);\n\t\tto_writer = queue_init(all_buffers_size * 2);\n\t}\n\n\tfrom_writer = queue_init(1);\n\n\tfragment_cache = cache_init(block_size, fragment_buffer_size);\n\tdata_cache = cache_init(block_size, data_buffer_size);\n\tpthread_create(&thread[0], NULL, reader, NULL);\n\tpthread_create(&thread[1], NULL, writer, NULL);\n\tpthread_create(&thread[2], NULL, progress_thread, NULL);\n\tinit_info();\n\tpthread_mutex_init(&fragment_mutex, NULL);\n\n\tfor (i = 0; i < processors; i++) {\n\t\tif (pthread_create(&inflator_thread[i], NULL, inflator, NULL) != 0)\n\t\t\tEXIT_UNSQUASH(\"Failed to create thread\\n\");\n\t}\n\n\tprintf(\"Parallel unsquashfs: Using %d processor%s\\n\", processors, processors == 1 ? \"\" : \"s\");\n\n\tif (pthread_sigmask(SIG_SETMASK, &old_mask, NULL) == -1)\n\t\tEXIT_UNSQUASH(\"Failed to set signal mask in initialise_threads\" \"\\n\");\n}\n\nvoid enable_progress_bar() {\n\tpthread_mutex_lock(&screen_mutex);\n\tprogress_enabled = progress;\n\tpthread_mutex_unlock(&screen_mutex);\n}\n\nvoid disable_progress_bar() {\n\tpthread_mutex_lock(&screen_mutex);\n\tif (progress_enabled) {\n\t\tprogress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns);\n\t\tprintf(\"\\n\");\n\t}\n\tprogress_enabled = FALSE;\n\tpthread_mutex_unlock(&screen_mutex);\n}\n\nvoid progressbar_error(char *fmt, ...) {\n\tva_list ap;\n\n\tpthread_mutex_lock(&screen_mutex);\n\n\tif (progress_enabled)\n\t\tfprintf(stderr, \"\\n\");\n\n\tva_start(ap, fmt);\n\tvfprintf(stderr, fmt, ap);\n\tva_end(ap);\n\n\tpthread_mutex_unlock(&screen_mutex);\n}\n\nvoid progressbar_info(char *fmt, ...) {\n\tva_list ap;\n\n\tpthread_mutex_lock(&screen_mutex);\n\n\tif (progress_enabled)\n\t\tprintf(\"\\n\");\n\n\tva_start(ap, fmt);\n\tvprintf(fmt, ap);\n\tva_end(ap);\n\n\tpthread_mutex_unlock(&screen_mutex);\n}\n\nvoid progress_bar(long long current, long long max, int columns) {\n\tchar rotate_list[] = { '|', '/', '-', '\\\\' };\n\tint max_digits, used, hashes, spaces;\n\tstatic int tty = -1;\n\n\tif (max == 0)\n\t\treturn;\n\n\tmax_digits = floor(log10(max)) + 1;\n\tused = max_digits * 2 + 11;\n\thashes = (current * (columns - used)) / max;\n\tspaces = columns - used - hashes;\n\n\tif ((current > max) || (columns - used < 0))\n\t\treturn;\n\n\tif (tty == -1)\n\t\ttty = isatty(STDOUT_FILENO);\n\tif (!tty) {\n\t\tstatic long long previous = -1;\n\n\t\t/*\n\t\t * Updating much more frequently than this results in huge\n\t\t * log files.\n\t\t */\n\t\tif ((current % 100) != 0 && current != max)\n\t\t\treturn;\n\t\t/* Don't update just to rotate the spinner. */\n\t\tif (current == previous)\n\t\t\treturn;\n\t\tprevious = current;\n\t}\n\n\tprintf(\"\\r[\");\n\n\twhile (hashes--)\n\t\tputchar('=');\n\n\tputchar(rotate_list[rotate]);\n\n\twhile (spaces--)\n\t\tputchar(' ');\n\n\tprintf(\"] %*lld/%*lld\", max_digits, current, max_digits, max);\n\tprintf(\" %3lld%%\", current * 100 / max);\n\tfflush(stdout);\n}\n\nint parse_number(char *arg, int *res) {\n\tchar *b;\n\tlong number = strtol(arg, &b, 10);\n\n\t/* check for trailing junk after number */\n\tif (*b != '\\0')\n\t\treturn 0;\n\n\t/*\n\t * check for strtol underflow or overflow in conversion.\n\t * Note: strtol can validly return LONG_MIN and LONG_MAX\n\t * if the user entered these values, but, additional code\n\t * to distinguish this scenario is unnecessary, because for\n\t * our purposes LONG_MIN and LONG_MAX are too large anyway\n\t */\n\tif (number == LONG_MIN || number == LONG_MAX)\n\t\treturn 0;\n\n\t/* reject negative numbers as invalid */\n\tif (number < 0)\n\t\treturn 0;\n\n\t/* check if long result will overflow signed int */\n\tif (number > INT_MAX)\n\t\treturn 0;\n\n\t*res = number;\n\treturn 1;\n}\n\n#define VERSION() \\\n\tprintf(\"unsquashfs version 4.3 (2014/05/12)\\n\");\\\n\tprintf(\"copyright (C) 2014 Phillip Lougher \"\\\n\t\t\"<phillip@squashfs.org.uk>\\n\\n\");\\\n    \tprintf(\"This program is free software; you can redistribute it and/or\"\\\n\t\t\"\\n\");\\\n\tprintf(\"modify it under the terms of the GNU General Public License\"\\\n\t\t\"\\n\");\\\n\tprintf(\"as published by the Free Software Foundation; either version \"\\\n\t\t\"2,\\n\");\\\n\tprintf(\"or (at your option) any later version.\\n\\n\");\\\n\tprintf(\"This program is distributed in the hope that it will be \"\\\n\t\t\"useful,\\n\");\\\n\tprintf(\"but WITHOUT ANY WARRANTY; without even the implied warranty of\"\\\n\t\t\"\\n\");\\\n\tprintf(\"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\"\\\n\t\t\"\\n\");\\\n\tprintf(\"GNU General Public License for more details.\\n\");\n\nint is_squashfs(char *filename) {\n\tif ((fd = open(filename, O_RDONLY)) == -1) {\n\t\tERROR(\"Could not open %s, because %s\\n\", filename, strerror(errno));\n\t\treturn FALSE;\n\t}\n\tchar *buffer = (char *)malloc(sizeof(char) * 0x67);\n\tif (buffer == NULL) {\n\t\tprintf(\"Memory allocation error!\\n\");\n\t\treturn FALSE;\n\t}\n\tint result = read(fd, buffer, 0x67);\n\tif (result != 0x67) {\n\t\tprintf(\"File reading error!\\n\");\n\t\treturn FALSE;\n\t}\n\tresult = memcmp(&buffer[0x64], \"cdx\", 3);\n\tfree(buffer);\n\n\tif (!result)\n\t\treturn FALSE;\n\n\tresult = read_super(filename);\n\tclose(fd);\n\treturn result;\n}\n\nint unsquashfs(char *squashfs, char *dest) {\n\tint stat_sys = FALSE;\n\tstruct pathnames *paths = NULL;\n\tstruct pathname *path = NULL;\n\tlong long directory_table_end;\n\tint fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT;\n\tint data_buffer_size = DATA_BUFFER_DEFAULT;\n\n\tpthread_mutex_init(&screen_mutex, NULL);\n\troot_process = geteuid() == 0;\n\tif (root_process)\n\t\tumask(0);\n\n#ifdef SQUASHFS_TRACE\n\t/*\n\t * Disable progress bar if full debug tracing is enabled.\n\t * The progress bar in this case just gets in the way of the\n\t * debug trace output\n\t */\n\tprogress = FALSE;\n#endif\n\n\tif ((fd = open(squashfs, O_RDONLY)) == -1) {\n\t\tERROR(\"Could not open %s, because %s\\n\", squashfs, strerror(errno));\n\t\texit(1);\n\t}\n\n\tif (read_super(squashfs) == FALSE)\n\t\texit(1);\n\n\tif (stat_sys) {\n\t\tsquashfs_stat(squashfs);\n\t\texit(0);\n\t}\n\n\tif (!check_compression(comp))\n\t\texit(1);\n\n\tblock_size = sBlk.s.block_size;\n\tblock_log = sBlk.s.block_log;\n\n\t/*\n\t * Sanity check block size and block log.\n\t *\n\t * Check they're within correct limits\n\t */\n\tif (block_size > SQUASHFS_FILE_MAX_SIZE || block_log > SQUASHFS_FILE_MAX_LOG)\n\t\tEXIT_UNSQUASH(\"Block size or block_log too large.\" \"  File system is corrupt.\\n\");\n\n\t/*\n\t * Check block_size and block_log match\n\t */\n\tif (block_size != (1 << block_log))\n\t\tEXIT_UNSQUASH(\"Block size and block_log do not match.\" \"  File system is corrupt.\\n\");\n\n\t/*\n\t * convert from queue size in Mbytes to queue size in\n\t * blocks.\n\t *\n\t * In doing so, check that the user supplied values do not\n\t * overflow a signed int\n\t */\n\tif (shift_overflow(fragment_buffer_size, 20 - block_log))\n\t\tEXIT_UNSQUASH(\"Fragment queue size is too large\\n\");\n\telse\n\t\tfragment_buffer_size <<= 20 - block_log;\n\n\tif (shift_overflow(data_buffer_size, 20 - block_log))\n\t\tEXIT_UNSQUASH(\"Data queue size is too large\\n\");\n\telse\n\t\tdata_buffer_size <<= 20 - block_log;\n\n\tinitialise_threads(fragment_buffer_size, data_buffer_size);\n\n\tfragment_data = malloc(block_size);\n\tif (fragment_data == NULL)\n\t\tEXIT_UNSQUASH(\"failed to allocate fragment_data\\n\");\n\n\tfile_data = malloc(block_size);\n\tif (file_data == NULL)\n\t\tEXIT_UNSQUASH(\"failed to allocate file_data\");\n\n\tdata = malloc(block_size);\n\tif (data == NULL)\n\t\tEXIT_UNSQUASH(\"failed to allocate data\\n\");\n\n\tcreated_inode = malloc(sBlk.s.inodes * sizeof(char *));\n\tif (created_inode == NULL)\n\t\tEXIT_UNSQUASH(\"failed to allocate created_inode\\n\");\n\n\tmemset(created_inode, 0, sBlk.s.inodes * sizeof(char *));\n\n\tif (s_ops.read_uids_guids() == FALSE)\n\t\tEXIT_UNSQUASH(\"failed to uid/gid table\\n\");\n\n\tif (s_ops.read_fragment_table(&directory_table_end) == FALSE)\n\t\tEXIT_UNSQUASH(\"failed to read fragment table\\n\");\n\n\tif (read_inode_table(sBlk.s.inode_table_start, sBlk.s.directory_table_start) == FALSE)\n\t\tEXIT_UNSQUASH(\"failed to read inode table\\n\");\n\n\tif (read_directory_table(sBlk.s.directory_table_start, directory_table_end) == FALSE)\n\t\tEXIT_UNSQUASH(\"failed to read directory table\\n\");\n\n\tif (no_xattrs)\n\t\tsBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK;\n\n\tif (read_xattrs_from_disk(fd, &sBlk.s) == 0)\n\t\tEXIT_UNSQUASH(\"failed to read the xattr table\\n\");\n\n\tif (path) {\n\t\tpaths = init_subdir();\n\t\tpaths = add_subdir(paths, path);\n\t}\n\n\tpre_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths);\n\n\tmemset(created_inode, 0, sBlk.s.inodes * sizeof(char *));\n\tinode_number = 1;\n\n\tprintf(\"%d inodes (%d blocks) to write\\n\\n\", total_inodes, total_inodes - total_files + total_blocks);\n\n\tenable_progress_bar();\n\n\tdir_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths);\n\n\tqueue_put(to_writer, NULL);\n\tqueue_get(from_writer);\n\n\tdisable_progress_bar();\n\n\tif (!lsonly) {\n\t\tprintf(\"\\n\");\n\t\tprintf(\"created %d files\\n\", file_count);\n\t\tprintf(\"created %d directories\\n\", dir_count);\n\t\tprintf(\"created %d symlinks\\n\", sym_count);\n\t\tprintf(\"created %d devices\\n\", dev_count);\n\t\tprintf(\"created %d fifos\\n\", fifo_count);\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "src/squashfs/unsquashfs_info.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * unsquashfs_info.c\n */\n\n#include <pthread.h>\n#include <sys/ioctl.h>\n#include <unistd.h>\n#include <signal.h>\n#include <sys/time.h>\n#include <stdio.h>\n#include <math.h>\n#include <stdarg.h>\n#include <errno.h>\n#include <stdlib.h>\n#include <dirent.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <string.h>\n\n#include \"squashfs_fs.h\"\n#include \"unsquashfs.h\"\n#include \"error.h\"\n\n#if defined(__CYGWIN__) || defined(__APPLE__)\n#\tdefine sigtimedwait(a,b,c) sigwaitinfo(a,b)\n#endif\n\n#ifdef __APPLE__\n#\tdefine sigwaitinfo(a,b) sigwait(a, b)\n#endif\n\nstatic int silent = 0;\nchar *pathname = NULL;\n\npthread_t info_thread;\n\nvoid disable_info() {\n\tif (pathname)\n\t\tfree(pathname);\n\n\tpathname = NULL;\n}\n\nvoid update_info(char *name) {\n\tif (pathname)\n\t\tfree(pathname);\n\n\tpathname = name;\n}\n\nvoid dump_state() {\n\tdisable_progress_bar();\n\n\tprintf(\"Queue and cache status dump\\n\");\n\tprintf(\"===========================\\n\");\n\n\tprintf(\"file buffer read queue (main thread -> reader thread)\\n\");\n\tdump_queue(to_reader);\n\n\tprintf(\"file buffer decompress queue (reader thread -> inflate\" \" thread(s))\\n\");\n\tdump_queue(to_inflate);\n\n\tprintf(\"file buffer write queue (main thread -> writer thread)\\n\");\n\tdump_queue(to_writer);\n\n\tprintf(\"\\nbuffer cache (uncompressed blocks and compressed blocks \" \"'in flight')\\n\");\n\tdump_cache(data_cache);\n\n\tprintf(\"fragment buffer cache (uncompressed frags and compressed\" \" frags 'in flight')\\n\");\n\tdump_cache(fragment_cache);\n\n\tenable_progress_bar();\n}\n\nvoid *info_thrd(void *arg) {\n\tsigset_t sigmask;\n\tstruct timespec timespec = {.tv_sec = 1,.tv_nsec = 0 };\n\tint sig, waiting = 0;\n\n\tsigemptyset(&sigmask);\n\tsigaddset(&sigmask, SIGQUIT);\n\tsigaddset(&sigmask, SIGHUP);\n\n\twhile (1) {\n\t\tif (waiting)\n\t\t\tsig = sigtimedwait(&sigmask, NULL, &timespec);\n\t\telse\n\t\t\tsig = sigwaitinfo(&sigmask, NULL);\n\n\t\tif (sig == -1) {\n\t\t\tswitch (errno) {\n\t\t\tcase EAGAIN:\n\t\t\t\t/* interval timed out */\n\t\t\t\twaiting = 0;\n\t\t\t\t/* FALLTHROUGH */\n\t\t\tcase EINTR:\n\t\t\t\t/* if waiting, the wait will be longer, but\n\t\t\t\t   that's OK */\n\t\t\t\tcontinue;\n\t\t\tdefault:\n\t\t\t\tBAD_ERROR(\"sigtimedwait/sigwaitinfo failed \" \"because %s\\n\", strerror(errno));\n\t\t\t}\n\t\t}\n\n\t\tif (sig == SIGQUIT && !waiting) {\n\t\t\tif (pathname)\n\t\t\t\tINFO(\"%s\\n\", pathname);\n\n\t\t\t/* set one second interval period, if ^\\ received\n\t\t\t   within then, dump queue and cache status */\n\t\t\twaiting = 1;\n\t\t} else\n\t\t\tdump_state();\n\t}\n}\n\nvoid init_info() {\n\tpthread_create(&info_thread, NULL, info_thrd, NULL);\n}\n"
  },
  {
    "path": "src/squashfs/unsquashfs_xattr.c",
    "content": "/*\n * Unsquash a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2010, 2012\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * unsquashfs_xattr.c\n */\n\n#include \"unsquashfs.h\"\n#include \"xattr.h\"\n\n#include <sys/xattr.h>\n\n#define NOSPACE_MAX 10\n\nextern int root_process;\nextern int user_xattrs;\n\nvoid write_xattr(char *pathname, unsigned int xattr) {\n\tunsigned int count;\n\tstruct xattr_list *xattr_list;\n\tint i;\n\tstatic int nonsuper_error = FALSE;\n\tstatic int ignore_xattrs = FALSE;\n\tstatic int nospace_error = 0;\n\n\tif (ignore_xattrs || xattr == SQUASHFS_INVALID_XATTR || sBlk.s.xattr_id_table_start == SQUASHFS_INVALID_BLK)\n\t\treturn;\n\n\txattr_list = get_xattr(xattr, &count, 1);\n\tif (xattr_list == NULL) {\n\t\tERROR(\"Failed to read xattrs for file %s\\n\", pathname);\n\t\treturn;\n\t}\n\n\tfor (i = 0; i < count; i++) {\n\t\tint prefix = xattr_list[i].type & SQUASHFS_XATTR_PREFIX_MASK;\n\n\t\tif (user_xattrs && prefix != SQUASHFS_XATTR_USER)\n\t\t\tcontinue;\n\n\t\tif (root_process || prefix == SQUASHFS_XATTR_USER) {\n\t\t\tint res = lsetxattr(pathname, xattr_list[i].full_name,\n\t\t\t\t\t\t\t\txattr_list[i].value, xattr_list[i].vsize, 0);\n\n\t\t\tif (res == -1) {\n\t\t\t\tif (errno == ENOTSUP) {\n\t\t\t\t\t/*\n\t\t\t\t\t * If the destination filesystem cannot\n\t\t\t\t\t * suppport xattrs, print error, and\n\t\t\t\t\t * disable xattr output as this error is\n\t\t\t\t\t * unlikely to go away, and printing\n\t\t\t\t\t * screenfulls of the same error message\n\t\t\t\t\t * is rather annoying\n\t\t\t\t\t */\n\t\t\t\t\tERROR(\"write_xattr: failed to write \" \"xattr %s for file %s because \" \"extended attributes are not \" \"supported by the destination \" \"filesystem\\n\", xattr_list[i].full_name, pathname);\n\t\t\t\t\tERROR(\"Ignoring xattrs in \" \"filesystem\\n\");\n\t\t\t\t\tERROR(\"To avoid this error message, \" \"specify -no-xattrs\\n\");\n\t\t\t\t\tignore_xattrs = TRUE;\n\t\t\t\t} else if ((errno == ENOSPC || errno == EDQUOT)\n\t\t\t\t\t\t   && nospace_error < NOSPACE_MAX) {\n\t\t\t\t\t/*\n\t\t\t\t\t * Many filesystems like ext2/3/4 have\n\t\t\t\t\t * limits on the amount of xattr\n\t\t\t\t\t * data that can be stored per file\n\t\t\t\t\t * (typically one block or 4K), so\n\t\t\t\t\t * we shouldn't disable xattr ouput,\n\t\t\t\t\t * as the error may be restriced to one\n\t\t\t\t\t * file only.  If we get a lot of these\n\t\t\t\t\t * then suppress the error messsage\n\t\t\t\t\t */\n\t\t\t\t\tERROR(\"write_xattr: failed to write \" \"xattr %s for file %s because \" \"no extended attribute space \" \"remaining (per file or \" \"filesystem limit)\\n\", xattr_list[i].full_name, pathname);\n\t\t\t\t\tif (++nospace_error == NOSPACE_MAX)\n\t\t\t\t\t\tERROR(\"%d of these errors \" \"printed, further error \" \"messages of this type \" \"are suppressed!\\n\", NOSPACE_MAX);\n\t\t\t\t} else\n\t\t\t\t\tERROR(\"write_xattr: failed to write \" \"xattr %s for file %s because \" \"%s\\n\", xattr_list[i].full_name, pathname, strerror(errno));\n\t\t\t}\n\t\t} else if (nonsuper_error == FALSE) {\n\t\t\t/*\n\t\t\t * if extract user xattrs only then\n\t\t\t * error message is suppressed, if not\n\t\t\t * print error, and then suppress further error\n\t\t\t * messages to avoid possible screenfulls of the\n\t\t\t * same error message!\n\t\t\t */\n\t\t\tERROR(\"write_xattr: could not write xattr %s \" \"for file %s because you're not \" \"superuser!\\n\", xattr_list[i].full_name, pathname);\n\t\t\tERROR(\"write_xattr: to avoid this error message, either\" \" specify -user-xattrs, -no-xattrs, or run as \" \"superuser!\\n\");\n\t\t\tERROR(\"Further error messages of this type are \" \"suppressed!\\n\");\n\t\t\tnonsuper_error = TRUE;\n\t\t}\n\t}\n\n\tfree_xattr(xattr_list, count);\n}\n"
  },
  {
    "path": "src/squashfs/xattr.c",
    "content": "/*\n * Create a squashfs filesystem.  This is a highly compressed read only\n * filesystem.\n *\n * Copyright (c) 2008, 2009, 2010, 2012, 2014\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * xattr.c\n */\n\n#define TRUE 1\n#define FALSE 0\n\n#include <unistd.h>\n#include <stdio.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <dirent.h>\n#include <string.h>\n#include <stdlib.h>\n#include <sys/xattr.h>\n\n#include \"squashfs_fs.h\"\n#include \"squashfs_swap.h\"\n#include \"mksquashfs.h\"\n#include \"xattr.h\"\n#include \"error.h\"\n#include \"progressbar.h\"\n\n/* compressed xattr table */\nstatic char *xattr_table = NULL;\nstatic unsigned int xattr_size = 0;\n\n/* cached uncompressed xattr data */\nstatic char *data_cache = NULL;\nstatic int cache_bytes = 0, cache_size = 0;\n\n/* cached uncompressed xattr id table */\nstatic struct squashfs_xattr_id *xattr_id_table = NULL;\nstatic int xattr_ids = 0;\n\n/* saved compressed xattr table */\nunsigned int sxattr_bytes = 0, stotal_xattr_bytes = 0;\n\n/* saved cached uncompressed xattr data */\nstatic char *sdata_cache = NULL;\nstatic int scache_bytes = 0;\n\n/* saved cached uncompressed xattr id table */\nstatic int sxattr_ids = 0;\n\n/* xattr hash table for value duplicate detection */\nstatic struct xattr_list *dupl_value[65536];\n\n/* xattr hash table for id duplicate detection */\nstatic struct dupl_id *dupl_id[65536];\n\n/* file system globals from mksquashfs.c */\nextern int no_xattrs, noX;\nextern long long bytes;\nextern int fd;\nextern unsigned int xattr_bytes, total_xattr_bytes;\n\n/* helper functions from mksquashfs.c */\nextern unsigned short get_checksum(char *, int, unsigned short);\nextern void write_destination(int, long long, int, void *);\nextern long long generic_write_table(int, void *, int, void *, int);\nextern int mangle(char *, char *, int, int, int, int);\nextern char *pathname(struct dir_ent *);\n\n/* helper functions and definitions from read_xattrs.c */\nextern int read_xattrs_from_disk(int, struct squashfs_super_block *);\nextern struct xattr_list *get_xattr(int, unsigned int *, int);\nextern struct prefix prefix_table[];\n\nstatic int get_prefix(struct xattr_list *xattr, char *name) {\n\tint i;\n\n\txattr->full_name = strdup(name);\n\n\tfor (i = 0; prefix_table[i].type != -1; i++) {\n\t\tstruct prefix *p = &prefix_table[i];\n\t\tif (strncmp(xattr->full_name, p->prefix, strlen(p->prefix)) == 0)\n\t\t\tbreak;\n\t}\n\n\tif (prefix_table[i].type != -1) {\n\t\txattr->name = xattr->full_name + strlen(prefix_table[i].prefix);\n\t\txattr->size = strlen(xattr->name);\n\t}\n\n\treturn prefix_table[i].type;\n}\n\nstatic int read_xattrs_from_system(char *filename, struct xattr_list **xattrs) {\n\tssize_t size, vsize;\n\tchar *xattr_names, *p;\n\tint i;\n\tstruct xattr_list *xattr_list = NULL;\n\n\twhile (1) {\n\t\tsize = llistxattr(filename, NULL, 0);\n\t\tif (size <= 0) {\n\t\t\tif (size < 0 && errno != ENOTSUP) {\n\t\t\t\tERROR_START(\"llistxattr for %s failed in \" \"read_attrs, because %s\", filename, strerror(errno));\n\t\t\t\tERROR_EXIT(\".  Ignoring\");\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\n\t\txattr_names = malloc(size);\n\t\tif (xattr_names == NULL)\n\t\t\tMEM_ERROR();\n\n\t\tsize = llistxattr(filename, xattr_names, size);\n\t\tif (size < 0) {\n\t\t\tfree(xattr_names);\n\t\t\tif (errno == ERANGE)\n\t\t\t\t/* xattr list grew?  Try again */\n\t\t\t\tcontinue;\n\t\t\telse {\n\t\t\t\tERROR_START(\"llistxattr for %s failed in \" \"read_attrs, because %s\", filename, strerror(errno));\n\t\t\t\tERROR_EXIT(\".  Ignoring\");\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\n\t\tbreak;\n\t}\n\n\tfor (i = 0, p = xattr_names; p < xattr_names + size; i++) {\n\t\tstruct xattr_list *x = realloc(xattr_list, (i + 1) * sizeof(struct xattr_list));\n\t\tif (x == NULL)\n\t\t\tMEM_ERROR();\n\t\txattr_list = x;\n\n\t\txattr_list[i].type = get_prefix(&xattr_list[i], p);\n\t\tp += strlen(p) + 1;\n\t\tif (xattr_list[i].type == -1) {\n\t\t\tERROR(\"Unrecognised xattr prefix %s\\n\", xattr_list[i].full_name);\n\t\t\tfree(xattr_list[i].full_name);\n\t\t\ti--;\n\t\t\tcontinue;\n\t\t}\n\n\t\twhile (1) {\n\t\t\tvsize = lgetxattr(filename, xattr_list[i].full_name, NULL, 0);\n\t\t\tif (vsize < 0) {\n\t\t\t\tERROR_START(\"lgetxattr failed for %s in \" \"read_attrs, because %s\", filename, strerror(errno));\n\t\t\t\tERROR_EXIT(\".  Ignoring\");\n\t\t\t\tfree(xattr_list[i].full_name);\n\t\t\t\tgoto failed;\n\t\t\t}\n\n\t\t\txattr_list[i].value = malloc(vsize);\n\t\t\tif (xattr_list[i].value == NULL)\n\t\t\t\tMEM_ERROR();\n\n\t\t\tvsize = lgetxattr(filename, xattr_list[i].full_name, xattr_list[i].value, vsize);\n\t\t\tif (vsize < 0) {\n\t\t\t\tfree(xattr_list[i].value);\n\t\t\t\tif (errno == ERANGE)\n\t\t\t\t\t/* xattr grew?  Try again */\n\t\t\t\t\tcontinue;\n\t\t\t\telse {\n\t\t\t\t\tERROR_START(\"lgetxattr failed for %s \" \"in read_attrs, because %s\", filename, strerror(errno));\n\t\t\t\t\tERROR_EXIT(\".  Ignoring\");\n\t\t\t\t\tfree(xattr_list[i].full_name);\n\t\t\t\t\tgoto failed;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\t\txattr_list[i].vsize = vsize;\n\n\t\tTRACE(\"read_xattrs_from_system: filename %s, xattr name %s,\" \" vsize %d\\n\", filename, xattr_list[i].full_name, xattr_list[i].vsize);\n\t}\n\tfree(xattr_names);\n\t*xattrs = xattr_list;\n\treturn i;\n\n failed:\n\twhile (--i >= 0) {\n\t\tfree(xattr_list[i].full_name);\n\t\tfree(xattr_list[i].value);\n\t}\n\tfree(xattr_list);\n\tfree(xattr_names);\n\treturn 0;\n}\n\nstatic int get_xattr_size(struct xattr_list *xattr) {\n\tint size = sizeof(struct squashfs_xattr_entry) + sizeof(struct squashfs_xattr_val) + xattr->size;\n\n\tif (xattr->type & XATTR_VALUE_OOL)\n\t\tsize += XATTR_VALUE_OOL_SIZE;\n\telse\n\t\tsize += xattr->vsize;\n\n\treturn size;\n}\n\nstatic void *get_xattr_space(unsigned int req_size, long long *disk) {\n\tint data_space;\n\tunsigned short c_byte;\n\n\t/*\n\t * Move and compress cached uncompressed data into xattr table.\n\t */\n\twhile (cache_bytes >= SQUASHFS_METADATA_SIZE) {\n\t\tif ((xattr_size - xattr_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) {\n\t\t\txattr_table = realloc(xattr_table, xattr_size + (SQUASHFS_METADATA_SIZE << 1) + 2);\n\t\t\tif (xattr_table == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t\txattr_size += (SQUASHFS_METADATA_SIZE << 1) + 2;\n\t\t}\n\n\t\tc_byte = mangle(xattr_table + xattr_bytes + BLOCK_OFFSET, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noX, 0);\n\t\tTRACE(\"Xattr block @ 0x%x, size %d\\n\", xattr_bytes, c_byte);\n\t\tSQUASHFS_SWAP_SHORTS(&c_byte, xattr_table + xattr_bytes, 1);\n\t\txattr_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET;\n\t\tmemmove(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE);\n\t\tcache_bytes -= SQUASHFS_METADATA_SIZE;\n\t}\n\n\t/*\n\t * Ensure there's enough space in the uncompressed data cache\n\t */\n\tdata_space = cache_size - cache_bytes;\n\tif (data_space < req_size) {\n\t\tint realloc_size = req_size - data_space;\n\t\tdata_cache = realloc(data_cache, cache_size + realloc_size);\n\t\tif (data_cache == NULL)\n\t\t\tMEM_ERROR();\n\t\tcache_size += realloc_size;\n\t}\n\n\tif (disk)\n\t\t*disk = ((long long)xattr_bytes << 16) | cache_bytes;\n\tcache_bytes += req_size;\n\treturn data_cache + cache_bytes - req_size;\n}\n\nstatic struct dupl_id *check_id_dupl(struct xattr_list *xattr_list, int xattrs) {\n\tstruct dupl_id *entry;\n\tint i;\n\tunsigned short checksum = 0;\n\n\t/* compute checksum over all xattrs */\n\tfor (i = 0; i < xattrs; i++) {\n\t\tstruct xattr_list *xattr = &xattr_list[i];\n\n\t\tchecksum = get_checksum(xattr->full_name, strlen(xattr->full_name), checksum);\n\t\tchecksum = get_checksum(xattr->value, xattr->vsize, checksum);\n\t}\n\n\tfor (entry = dupl_id[checksum]; entry; entry = entry->next) {\n\t\tif (entry->xattrs != xattrs)\n\t\t\tcontinue;\n\n\t\tfor (i = 0; i < xattrs; i++) {\n\t\t\tstruct xattr_list *xattr = &xattr_list[i];\n\t\t\tstruct xattr_list *dup_xattr = &entry->xattr_list[i];\n\n\t\t\tif (strcmp(xattr->full_name, dup_xattr->full_name))\n\t\t\t\tbreak;\n\n\t\t\tif (memcmp(xattr->value, dup_xattr->value, xattr->vsize))\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (i == xattrs)\n\t\t\tbreak;\n\t}\n\n\tif (entry == NULL) {\n\t\t/* no duplicate exists */\n\t\tentry = malloc(sizeof(*entry));\n\t\tif (entry == NULL)\n\t\t\tMEM_ERROR();\n\t\tentry->xattrs = xattrs;\n\t\tentry->xattr_list = xattr_list;\n\t\tentry->xattr_id = SQUASHFS_INVALID_XATTR;\n\t\tentry->next = dupl_id[checksum];\n\t\tdupl_id[checksum] = entry;\n\t}\n\n\treturn entry;\n}\n\nstatic void check_value_dupl(struct xattr_list *xattr) {\n\tstruct xattr_list *entry;\n\n\tif (xattr->vsize < XATTR_VALUE_OOL_SIZE)\n\t\treturn;\n\n\t/* Check if this is a duplicate of an existing value */\n\txattr->vchecksum = get_checksum(xattr->value, xattr->vsize, 0);\n\tfor (entry = dupl_value[xattr->vchecksum]; entry; entry = entry->vnext) {\n\t\tif (entry->vsize != xattr->vsize)\n\t\t\tcontinue;\n\n\t\tif (memcmp(entry->value, xattr->value, xattr->vsize) == 0)\n\t\t\tbreak;\n\t}\n\n\tif (entry == NULL) {\n\t\t/*\n\t\t * No duplicate exists, add to hash table, and mark as\n\t\t * requiring writing\n\t\t */\n\t\txattr->vnext = dupl_value[xattr->vchecksum];\n\t\tdupl_value[xattr->vchecksum] = xattr;\n\t\txattr->ool_value = SQUASHFS_INVALID_BLK;\n\t} else {\n\t\t/*\n\t\t * Duplicate exists, make type XATTR_VALUE_OOL, and\n\t\t * remember where the duplicate is\n\t\t */\n\t\txattr->type |= XATTR_VALUE_OOL;\n\t\txattr->ool_value = entry->ool_value;\n\t\t/* on appending don't free duplicate values because the\n\t\t * duplicate value already points to the non-duplicate value */\n\t\tif (xattr->value != entry->value) {\n\t\t\tfree(xattr->value);\n\t\t\txattr->value = entry->value;\n\t\t}\n\t}\n}\n\nstatic int get_xattr_id(int xattrs, struct xattr_list *xattr_list, long long xattr_disk, struct dupl_id *xattr_dupl) {\n\tint i, size = 0;\n\tstruct squashfs_xattr_id *xattr_id;\n\n\txattr_id_table = realloc(xattr_id_table, (xattr_ids + 1) * sizeof(struct squashfs_xattr_id));\n\tif (xattr_id_table == NULL)\n\t\tMEM_ERROR();\n\n\t/* get total uncompressed size of xattr data, needed for stat */\n\tfor (i = 0; i < xattrs; i++)\n\t\tsize += strlen(xattr_list[i].full_name) + 1 + xattr_list[i].vsize;\n\n\txattr_id = &xattr_id_table[xattr_ids];\n\txattr_id->xattr = xattr_disk;\n\txattr_id->count = xattrs;\n\txattr_id->size = size;\n\n\t/*\n\t * keep track of total uncompressed xattr data, needed for mksquashfs\n\t * file system summary\n\t */\n\ttotal_xattr_bytes += size;\n\n\txattr_dupl->xattr_id = xattr_ids++;\n\treturn xattr_dupl->xattr_id;\n}\n\nlong long write_xattrs() {\n\tunsigned short c_byte;\n\tint i, avail_bytes;\n\tchar *datap = data_cache;\n\tlong long start_bytes = bytes;\n\tstruct squashfs_xattr_table header;\n\n\tif (xattr_ids == 0)\n\t\treturn SQUASHFS_INVALID_BLK;\n\n\t/*\n\t * Move and compress cached uncompressed data into xattr table.\n\t */\n\twhile (cache_bytes) {\n\t\tif ((xattr_size - xattr_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) {\n\t\t\txattr_table = realloc(xattr_table, xattr_size + (SQUASHFS_METADATA_SIZE << 1) + 2);\n\t\t\tif (xattr_table == NULL)\n\t\t\t\tMEM_ERROR();\n\t\t\txattr_size += (SQUASHFS_METADATA_SIZE << 1) + 2;\n\t\t}\n\n\t\tavail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes;\n\t\tc_byte = mangle(xattr_table + xattr_bytes + BLOCK_OFFSET, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noX, 0);\n\t\tTRACE(\"Xattr block @ 0x%x, size %d\\n\", xattr_bytes, c_byte);\n\t\tSQUASHFS_SWAP_SHORTS(&c_byte, xattr_table + xattr_bytes, 1);\n\t\txattr_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET;\n\t\tdatap += avail_bytes;\n\t\tcache_bytes -= avail_bytes;\n\t}\n\n\t/*\n\t * Write compressed xattr table to file system\n\t */\n\twrite_destination(fd, bytes, xattr_bytes, xattr_table);\n\tbytes += xattr_bytes;\n\n\t/*\n\t * Swap if necessary the xattr id table\n\t */\n\tfor (i = 0; i < xattr_ids; i++)\n\t\tSQUASHFS_INSWAP_XATTR_ID(&xattr_id_table[i]);\n\n\theader.xattr_ids = xattr_ids;\n\theader.xattr_table_start = start_bytes;\n\tSQUASHFS_INSWAP_XATTR_TABLE(&header);\n\n\treturn generic_write_table(xattr_ids * sizeof(struct squashfs_xattr_id), xattr_id_table, sizeof(header), &header, noX);\n}\n\nint generate_xattrs(int xattrs, struct xattr_list *xattr_list) {\n\tint total_size, i;\n\tint xattr_value_max;\n\tvoid *xp;\n\tlong long xattr_disk;\n\tstruct dupl_id *xattr_dupl;\n\n\t/*\n\t * check if the file xattrs are a complete duplicate of a pre-existing\n\t * id\n\t */\n\txattr_dupl = check_id_dupl(xattr_list, xattrs);\n\tif (xattr_dupl->xattr_id != SQUASHFS_INVALID_XATTR)\n\t\treturn xattr_dupl->xattr_id;\n\n\t/*\n\t * Scan the xattr_list deciding which type to assign to each\n\t * xattr.  The choice is fairly straightforward, and depends on the\n\t * size of each xattr name/value and the overall size of the\n\t * resultant xattr list stored in the xattr metadata table.\n\t *\n\t * Choices are whether to store data inline or out of line.\n\t *\n\t * The overall goal is to optimise xattr scanning and lookup, and\n\t * to enable the file system layout to scale from a couple of\n\t * small xattr name/values to a large number of large xattr\n\t * names/values without affecting performance.  While hopefully\n\t * enabling the common case of a couple of small xattr name/values\n\t * to be stored efficiently\n\t *\n\t * Code repeatedly scans, doing the following\n\t *      move xattr data out of line if it exceeds\n\t *      xattr_value_max.  Where xattr_value_max is\n\t *      initially XATTR_INLINE_MAX.  If the final uncompressed\n\t *      xattr list is larger than XATTR_TARGET_MAX then more\n\t *      aggressively move xattr data out of line by repeatedly\n\t *      setting inline threshold to 1/2, then 1/4, 1/8 of\n\t *      XATTR_INLINE_MAX until target achieved or there's\n\t *      nothing left to move out of line\n\t */\n\txattr_value_max = XATTR_INLINE_MAX;\n\twhile (1) {\n\t\tfor (total_size = 0, i = 0; i < xattrs; i++) {\n\t\t\tstruct xattr_list *xattr = &xattr_list[i];\n\t\t\txattr->type &= XATTR_PREFIX_MASK;\t/* all inline */\n\t\t\tif (xattr->vsize > xattr_value_max)\n\t\t\t\txattr->type |= XATTR_VALUE_OOL;\n\n\t\t\ttotal_size += get_xattr_size(xattr);\n\t\t}\n\n\t\t/*\n\t\t * If the total size of the uncompressed xattr list is <=\n\t\t * XATTR_TARGET_MAX we're done\n\t\t */\n\t\tif (total_size <= XATTR_TARGET_MAX)\n\t\t\tbreak;\n\n\t\tif (xattr_value_max == XATTR_VALUE_OOL_SIZE)\n\t\t\tbreak;\n\n\t\t/*\n\t\t * Inline target not yet at minimum and so reduce it, and\n\t\t * try again\n\t\t */\n\t\txattr_value_max /= 2;\n\t\tif (xattr_value_max < XATTR_VALUE_OOL_SIZE)\n\t\t\txattr_value_max = XATTR_VALUE_OOL_SIZE;\n\t}\n\n\t/*\n\t * Check xattr values for duplicates\n\t */\n\tfor (i = 0; i < xattrs; i++) {\n\t\tcheck_value_dupl(&xattr_list[i]);\n\t}\n\n\t/*\n\t * Add each out of line value to the file system xattr table\n\t * if it doesn't already exist as a duplicate\n\t */\n\tfor (i = 0; i < xattrs; i++) {\n\t\tstruct xattr_list *xattr = &xattr_list[i];\n\n\t\tif ((xattr->type & XATTR_VALUE_OOL) && (xattr->ool_value == SQUASHFS_INVALID_BLK)) {\n\t\t\tstruct squashfs_xattr_val val;\n\t\t\tint size = sizeof(val) + xattr->vsize;\n\t\t\txp = get_xattr_space(size, &xattr->ool_value);\n\t\t\tval.vsize = xattr->vsize;\n\t\t\tSQUASHFS_SWAP_XATTR_VAL(&val, xp);\n\t\t\tmemcpy(xp + sizeof(val), xattr->value, xattr->vsize);\n\t\t}\n\t}\n\n\t/*\n\t * Create xattr list and add to file system xattr table\n\t */\n\tget_xattr_space(0, &xattr_disk);\n\tfor (i = 0; i < xattrs; i++) {\n\t\tstruct xattr_list *xattr = &xattr_list[i];\n\t\tstruct squashfs_xattr_entry entry;\n\t\tstruct squashfs_xattr_val val;\n\n\t\txp = get_xattr_space(sizeof(entry) + xattr->size, NULL);\n\t\tentry.type = xattr->type;\n\t\tentry.size = xattr->size;\n\t\tSQUASHFS_SWAP_XATTR_ENTRY(&entry, xp);\n\t\tmemcpy(xp + sizeof(entry), xattr->name, xattr->size);\n\n\t\tif (xattr->type & XATTR_VALUE_OOL) {\n\t\t\tint size = sizeof(val) + XATTR_VALUE_OOL_SIZE;\n\t\t\txp = get_xattr_space(size, NULL);\n\t\t\tval.vsize = XATTR_VALUE_OOL_SIZE;\n\t\t\tSQUASHFS_SWAP_XATTR_VAL(&val, xp);\n\t\t\tSQUASHFS_SWAP_LONG_LONGS(&xattr->ool_value, xp + sizeof(val), 1);\n\t\t} else {\n\t\t\tint size = sizeof(val) + xattr->vsize;\n\t\t\txp = get_xattr_space(size, &xattr->ool_value);\n\t\t\tval.vsize = xattr->vsize;\n\t\t\tSQUASHFS_SWAP_XATTR_VAL(&val, xp);\n\t\t\tmemcpy(xp + sizeof(val), xattr->value, xattr->vsize);\n\t\t}\n\t}\n\n\t/*\n\t * Add to xattr id lookup table\n\t */\n\treturn get_xattr_id(xattrs, xattr_list, xattr_disk, xattr_dupl);\n}\n\nint read_xattrs(void *d) {\n\tstruct dir_ent *dir_ent = d;\n\tstruct inode_info *inode = dir_ent->inode;\n\tchar *filename = pathname(dir_ent);\n\tstruct xattr_list *xattr_list;\n\tint xattrs;\n\n\tif (no_xattrs || IS_PSEUDO(inode) || inode->root_entry)\n\t\treturn SQUASHFS_INVALID_XATTR;\n\n\txattrs = read_xattrs_from_system(filename, &xattr_list);\n\tif (xattrs == 0)\n\t\treturn SQUASHFS_INVALID_XATTR;\n\n\treturn generate_xattrs(xattrs, xattr_list);\n}\n\n/*\n * Add the existing xattr ids and xattr metadata in the file system being\n * appended to, to the in-memory xattr cache.  This allows duplicate checking to\n * take place against the xattrs already in the file system being appended to,\n * and ensures the pre-existing xattrs are written out along with any new xattrs\n */\nint get_xattrs(int fd, struct squashfs_super_block *sBlk) {\n\tint ids, res, i, id;\n\tunsigned int count;\n\n\tTRACE(\"get_xattrs\\n\");\n\n\tres = read_xattrs_from_disk(fd, sBlk);\n\tif (res == SQUASHFS_INVALID_BLK || res == 0)\n\t\tgoto done;\n\tids = res;\n\n\t/*\n\t * for each xattr id read and construct its list of xattr\n\t * name:value pairs, and add them to the in-memory xattr cache\n\t */\n\tfor (i = 0; i < ids; i++) {\n\t\tstruct xattr_list *xattr_list = get_xattr(i, &count, 0);\n\t\tif (xattr_list == NULL) {\n\t\t\tres = 0;\n\t\t\tgoto done;\n\t\t}\n\t\tid = generate_xattrs(count, xattr_list);\n\n\t\t/*\n\t\t * Sanity check, the new xattr id should be the same as the\n\t\t * xattr id in the original file system\n\t\t */\n\t\tif (id != i) {\n\t\t\tERROR(\"BUG, different xattr_id in get_xattrs\\n\");\n\t\t\tres = 0;\n\t\t\tgoto done;\n\t\t}\n\t}\n\n done:\n\treturn res;\n}\n\n/*\n * Save current state of xattrs, needed for restoring state in the event of an\n * abort in appending\n */\nvoid save_xattrs() {\n\t/* save the current state of the compressed xattr data */\n\tsxattr_bytes = xattr_bytes;\n\tstotal_xattr_bytes = total_xattr_bytes;\n\n\t/*\n\t * save the current state of the cached uncompressed xattr data.\n\t * Note we have to save the contents of the data cache because future\n\t * operations will delete the current contents\n\t */\n\tsdata_cache = malloc(cache_bytes);\n\tif (sdata_cache == NULL)\n\t\tMEM_ERROR();\n\n\tmemcpy(sdata_cache, data_cache, cache_bytes);\n\tscache_bytes = cache_bytes;\n\n\t/* save the current state of the xattr id table */\n\tsxattr_ids = xattr_ids;\n}\n\n/*\n * Restore xattrs in the event of an abort in appending\n */\nvoid restore_xattrs() {\n\t/* restore the state of the compressed xattr data */\n\txattr_bytes = sxattr_bytes;\n\ttotal_xattr_bytes = stotal_xattr_bytes;\n\n\t/* restore the state of the uncomoressed xattr data */\n\tmemcpy(data_cache, sdata_cache, scache_bytes);\n\tcache_bytes = scache_bytes;\n\n\t/* restore the state of the xattr id table */\n\txattr_ids = sxattr_ids;\n}\n"
  },
  {
    "path": "src/squashfs/xz_wrapper.c",
    "content": "/*\n * Copyright (c) 2010, 2011, 2012, 2013\n * Phillip Lougher <phillip@squashfs.org.uk>\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 * 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 * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * xz_wrapper.c\n *\n * Support for XZ (LZMA2) compression using XZ Utils liblzma\n * http://tukaani.org/xz/\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <lzma.h>\n\n#include \"squashfs_fs.h\"\n#include \"xz_wrapper.h\"\n#include \"compressor.h\"\n\nstatic struct bcj bcj[] = {\n\t{\"x86\", LZMA_FILTER_X86, 0},\n\t{\"powerpc\", LZMA_FILTER_POWERPC, 0},\n\t{\"ia64\", LZMA_FILTER_IA64, 0},\n\t{\"arm\", LZMA_FILTER_ARM, 0},\n\t{\"armthumb\", LZMA_FILTER_ARMTHUMB, 0},\n\t{\"sparc\", LZMA_FILTER_SPARC, 0},\n\t{NULL, LZMA_VLI_UNKNOWN, 0}\n};\n\nstatic int filter_count = 1;\nstatic int dictionary_size = 0;\nstatic float dictionary_percent = 0;\n\n/*\n * This function is called by the options parsing code in mksquashfs.c\n * to parse any -X compressor option.\n *\n * Two specific options are supported:\n *\t-Xbcj\n *\t-Xdict-size\n *\n * This function returns:\n *\t>=0 (number of additional args parsed) on success\n *\t-1 if the option was unrecognised, or\n *\t-2 if the option was recognised, but otherwise bad in\n *\t   some way (e.g. invalid parameter)\n *\n * Note: this function sets internal compressor state, but does not\n * pass back the results of the parsing other than success/failure.\n * The xz_dump_options() function is called later to get the options in\n * a format suitable for writing to the filesystem.\n */\nstatic int xz_options(char *argv[], int argc) {\n\tint i;\n\tchar *name;\n\n\tif (strcmp(argv[0], \"-Xbcj\") == 0) {\n\t\tif (argc < 2) {\n\t\t\tfprintf(stderr, \"xz: -Xbcj missing filter\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\tname = argv[1];\n\t\twhile (name[0] != '\\0') {\n\t\t\tfor (i = 0; bcj[i].name; i++) {\n\t\t\t\tint n = strlen(bcj[i].name);\n\t\t\t\tif ((strncmp(name, bcj[i].name, n) == 0) && (name[n] == '\\0' || name[n] == ',')) {\n\t\t\t\t\tif (bcj[i].selected == 0) {\n\t\t\t\t\t\tbcj[i].selected = 1;\n\t\t\t\t\t\tfilter_count++;\n\t\t\t\t\t}\n\t\t\t\t\tname += name[n] == ',' ? n + 1 : n;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (bcj[i].name == NULL) {\n\t\t\t\tfprintf(stderr, \"xz: -Xbcj unrecognised \" \"filter\\n\");\n\t\t\t\tgoto failed;\n\t\t\t}\n\t\t}\n\n\t\treturn 1;\n\t} else if (strcmp(argv[0], \"-Xdict-size\") == 0) {\n\t\tchar *b;\n\t\tfloat size;\n\n\t\tif (argc < 2) {\n\t\t\tfprintf(stderr, \"xz: -Xdict-size missing dict-size\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\tsize = strtof(argv[1], &b);\n\t\tif (*b == '%') {\n\t\t\tif (size <= 0 || size > 100) {\n\t\t\t\tfprintf(stderr, \"xz: -Xdict-size percentage \" \"should be 0 < dict-size <= 100\\n\");\n\t\t\t\tgoto failed;\n\t\t\t}\n\n\t\t\tdictionary_percent = size;\n\t\t\tdictionary_size = 0;\n\t\t} else {\n\t\t\tif ((float)((int)size) != size) {\n\t\t\t\tfprintf(stderr, \"xz: -Xdict-size can't be \" \"fractional unless a percentage of the\" \" block size\\n\");\n\t\t\t\tgoto failed;\n\t\t\t}\n\n\t\t\tdictionary_percent = 0;\n\t\t\tdictionary_size = (int)size;\n\n\t\t\tif (*b == 'k' || *b == 'K')\n\t\t\t\tdictionary_size *= 1024;\n\t\t\telse if (*b == 'm' || *b == 'M')\n\t\t\t\tdictionary_size *= 1024 * 1024;\n\t\t\telse if (*b != '\\0') {\n\t\t\t\tfprintf(stderr, \"xz: -Xdict-size invalid \" \"dict-size\\n\");\n\t\t\t\tgoto failed;\n\t\t\t}\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\treturn -1;\n\n failed:\n\treturn -2;\n}\n\n/*\n * This function is called after all options have been parsed.\n * It is used to do post-processing on the compressor options using\n * values that were not expected to be known at option parse time.\n *\n * In this case block_size may not be known until after -Xdict-size has\n * been processed (in the case where -b is specified after -Xdict-size)\n *\n * This function returns 0 on successful post processing, or\n *\t\t\t-1 on error\n */\nstatic int xz_options_post(int block_size) {\n\t/*\n\t * if -Xdict-size has been specified use this to compute the datablock\n\t * dictionary size\n\t */\n\tif (dictionary_size || dictionary_percent) {\n\t\tint n;\n\n\t\tif (dictionary_size) {\n\t\t\tif (dictionary_size > block_size) {\n\t\t\t\tfprintf(stderr, \"xz: -Xdict-size is larger than\" \" block_size\\n\");\n\t\t\t\tgoto failed;\n\t\t\t}\n\t\t} else\n\t\t\tdictionary_size = block_size * dictionary_percent / 100;\n\n\t\tif (dictionary_size < 8192) {\n\t\t\tfprintf(stderr, \"xz: -Xdict-size should be 8192 bytes \" \"or larger\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t\t/*\n\t\t * dictionary_size must be storable in xz header as either\n\t\t * 2^n or as  2^n+2^(n+1)\n\t\t */\n\t\tn = ffs(dictionary_size) - 1;\n\t\tif (dictionary_size != (1 << n) && dictionary_size != ((1 << n) + (1 << (n + 1)))) {\n\t\t\tfprintf(stderr, \"xz: -Xdict-size is an unsupported \" \"value, dict-size must be storable in xz \" \"header\\n\");\n\t\t\tfprintf(stderr, \"as either 2^n or as 2^n+2^(n+1).  \" \"Example dict-sizes are 75%%, 50%%, 37.5%%, \" \"25%%,\\n\");\n\t\t\tfprintf(stderr, \"or 32K, 16K, 8K etc.\\n\");\n\t\t\tgoto failed;\n\t\t}\n\n\t} else\n\t\t/* No -Xdict-size specified, use defaults */\n\t\tdictionary_size = block_size;\n\n\treturn 0;\n\n failed:\n\treturn -1;\n}\n\n/*\n * This function is called by mksquashfs to dump the parsed\n * compressor options in a format suitable for writing to the\n * compressor options field in the filesystem (stored immediately\n * after the superblock).\n *\n * This function returns a pointer to the compression options structure\n * to be stored (and the size), or NULL if there are no compression\n * options\n */\nstatic void *xz_dump_options(int block_size, int *size) {\n\tstatic struct comp_opts comp_opts;\n\tint flags = 0, i;\n\n\t/*\n\t * don't store compressor specific options in file system if the\n\t * default options are being used - no compressor options in the\n\t * file system means the default options are always assumed\n\t *\n\t * Defaults are:\n\t *  metadata dictionary size: SQUASHFS_METADATA_SIZE\n\t *  datablock dictionary size: block_size\n\t *  1 filter\n\t */\n\tif (dictionary_size == block_size && filter_count == 1)\n\t\treturn NULL;\n\n\tfor (i = 0; bcj[i].name; i++)\n\t\tflags |= bcj[i].selected << i;\n\n\tcomp_opts.dictionary_size = dictionary_size;\n\tcomp_opts.flags = flags;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(&comp_opts);\n\n\t*size = sizeof(comp_opts);\n\treturn &comp_opts;\n}\n\n/*\n * This function is a helper specifically for the append mode of\n * mksquashfs.  Its purpose is to set the internal compressor state\n * to the stored compressor options in the passed compressor options\n * structure.\n *\n * In effect this function sets up the compressor options\n * to the same state they were when the filesystem was originally\n * generated, this is to ensure on appending, the compressor uses\n * the same compression options that were used to generate the\n * original filesystem.\n *\n * Note, even if there are no compressor options, this function is still\n * called with an empty compressor structure (size == 0), to explicitly\n * set the default options, this is to ensure any user supplied\n * -X options on the appending mksquashfs command line are over-ridden\n *\n * This function returns 0 on sucessful extraction of options, and\n *\t\t\t-1 on error\n */\nstatic int xz_extract_options(int block_size, void *buffer, int size) {\n\tstruct comp_opts *comp_opts = buffer;\n\tint flags, i, n;\n\n\tif (size == 0) {\n\t\t/* set defaults */\n\t\tdictionary_size = block_size;\n\t\tflags = 0;\n\t} else {\n\t\t/* check passed comp opts struct is of the correct length */\n\t\tif (size != sizeof(struct comp_opts))\n\t\t\tgoto failed;\n\n\t\tSQUASHFS_INSWAP_COMP_OPTS(comp_opts);\n\n\t\tdictionary_size = comp_opts->dictionary_size;\n\t\tflags = comp_opts->flags;\n\n\t\t/*\n\t\t * check that the dictionary size seems correct - the dictionary\n\t\t * size should 2^n or 2^n+2^(n+1)\n\t\t */\n\t\tn = ffs(dictionary_size) - 1;\n\t\tif (dictionary_size != (1 << n) && dictionary_size != ((1 << n) + (1 << (n + 1))))\n\t\t\tgoto failed;\n\t}\n\n\tfilter_count = 1;\n\tfor (i = 0; bcj[i].name; i++) {\n\t\tif ((flags >> i) & 1) {\n\t\t\tbcj[i].selected = 1;\n\t\t\tfilter_count++;\n\t\t} else\n\t\t\tbcj[i].selected = 0;\n\t}\n\n\treturn 0;\n\n failed:\n\tfprintf(stderr, \"xz: error reading stored compressor options from \" \"filesystem!\\n\");\n\n\treturn -1;\n}\n\nvoid xz_display_options(void *buffer, int size) {\n\tstruct comp_opts *comp_opts = buffer;\n\tint dictionary_size, flags, printed;\n\tint i, n;\n\n\t/* check passed comp opts struct is of the correct length */\n\tif (size != sizeof(struct comp_opts))\n\t\tgoto failed;\n\n\tSQUASHFS_INSWAP_COMP_OPTS(comp_opts);\n\n\tdictionary_size = comp_opts->dictionary_size;\n\tflags = comp_opts->flags;\n\n\t/*\n\t * check that the dictionary size seems correct - the dictionary\n\t * size should 2^n or 2^n+2^(n+1)\n\t */\n\tn = ffs(dictionary_size) - 1;\n\tif (dictionary_size != (1 << n) && dictionary_size != ((1 << n) + (1 << (n + 1))))\n\t\tgoto failed;\n\n\tprintf(\"\\tDictionary size %d\\n\", dictionary_size);\n\n\tprinted = 0;\n\tfor (i = 0; bcj[i].name; i++) {\n\t\tif ((flags >> i) & 1) {\n\t\t\tif (printed)\n\t\t\t\tprintf(\", \");\n\t\t\telse\n\t\t\t\tprintf(\"\\tFilters selected: \");\n\t\t\tprintf(\"%s\", bcj[i].name);\n\t\t\tprinted = 1;\n\t\t}\n\t}\n\n\tif (!printed)\n\t\tprintf(\"\\tNo filters specified\\n\");\n\telse\n\t\tprintf(\"\\n\");\n\n\treturn;\n\n failed:\n\tfprintf(stderr, \"xz: error reading stored compressor options from \" \"filesystem!\\n\");\n}\n\n/*\n * This function is called by mksquashfs to initialise the\n * compressor, before compress() is called.\n *\n * This function returns 0 on success, and\n *\t\t\t-1 on error\n */\nstatic int xz_init(void **strm, int block_size, int datablock) {\n\tint i, j, filters = datablock ? filter_count : 1;\n\tstruct filter *filter = malloc(filters * sizeof(struct filter));\n\tstruct xz_stream *stream;\n\n\tif (filter == NULL)\n\t\tgoto failed;\n\n\tstream = *strm = malloc(sizeof(struct xz_stream));\n\tif (stream == NULL)\n\t\tgoto failed2;\n\n\tstream->filter = filter;\n\tstream->filters = filters;\n\n\tmemset(filter, 0, filters * sizeof(struct filter));\n\n\tstream->dictionary_size = datablock ? dictionary_size : SQUASHFS_METADATA_SIZE;\n\n\tfilter[0].filter[0].id = LZMA_FILTER_LZMA2;\n\tfilter[0].filter[0].options = &stream->opt;\n\tfilter[0].filter[1].id = LZMA_VLI_UNKNOWN;\n\n\tfor (i = 0, j = 1; datablock && bcj[i].name; i++) {\n\t\tif (bcj[i].selected) {\n\t\t\tfilter[j].buffer = malloc(block_size);\n\t\t\tif (filter[j].buffer == NULL)\n\t\t\t\tgoto failed3;\n\t\t\tfilter[j].filter[0].id = bcj[i].id;\n\t\t\tfilter[j].filter[1].id = LZMA_FILTER_LZMA2;\n\t\t\tfilter[j].filter[1].options = &stream->opt;\n\t\t\tfilter[j].filter[2].id = LZMA_VLI_UNKNOWN;\n\t\t\tj++;\n\t\t}\n\t}\n\n\treturn 0;\n\n failed3:\n\tfor (i = 1; i < filters; i++)\n\t\tfree(filter[i].buffer);\n\tfree(stream);\n\n failed2:\n\tfree(filter);\n\n failed:\n\treturn -1;\n}\n\nstatic int xz_compress(void *strm, void *dest, void *src, int size, int block_size, int *error) {\n\tint i;\n\tlzma_ret res = 0;\n\tstruct xz_stream *stream = strm;\n\tstruct filter *selected = NULL;\n\n\tstream->filter[0].buffer = dest;\n\n\tfor (i = 0; i < stream->filters; i++) {\n\t\tstruct filter *filter = &stream->filter[i];\n\n\t\tif (lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))\n\t\t\tgoto failed;\n\n\t\tstream->opt.dict_size = stream->dictionary_size;\n\n\t\tfilter->length = 0;\n\t\tres = lzma_stream_buffer_encode(filter->filter, LZMA_CHECK_CRC32, NULL, src, size, filter->buffer, &filter->length, block_size);\n\n\t\tif (res == LZMA_OK) {\n\t\t\tif (!selected || selected->length > filter->length)\n\t\t\t\tselected = filter;\n\t\t} else if (res != LZMA_BUF_ERROR)\n\t\t\tgoto failed;\n\t}\n\n\tif (!selected)\n\t\t/*\n\t\t * Output buffer overflow.  Return out of buffer space\n\t\t */\n\t\treturn 0;\n\n\tif (selected->buffer != dest)\n\t\tmemcpy(dest, selected->buffer, selected->length);\n\n\treturn (int)selected->length;\n\n failed:\n\t/*\n\t * All other errors return failure, with the compressor\n\t * specific error code in *error\n\t */\n\t*error = res;\n\treturn -1;\n}\n\nstatic int xz_uncompress(void *dest, void *src, int size, int outsize, int *error) {\n\tsize_t src_pos = 0;\n\tsize_t dest_pos = 0;\n\tuint64_t memlimit = MEMLIMIT;\n\n\tlzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL,\n\t\t\t\t\t\t\t\t\t\t\t src, &src_pos, size, dest, &dest_pos, outsize);\n\n\tif (res == LZMA_OK && size == (int)src_pos)\n\t\treturn (int)dest_pos;\n\telse {\n\t\t*error = res;\n\t\treturn -1;\n\t}\n}\n\nvoid xz_usage() {\n\tfprintf(stderr, \"\\t  -Xbcj filter1,filter2,...,filterN\\n\");\n\tfprintf(stderr, \"\\t\\tCompress using filter1,filter2,...,filterN in\");\n\tfprintf(stderr, \" turn\\n\\t\\t(in addition to no filter), and choose\");\n\tfprintf(stderr, \" the best compression.\\n\");\n\tfprintf(stderr, \"\\t\\tAvailable filters: x86, arm, armthumb,\");\n\tfprintf(stderr, \" powerpc, sparc, ia64\\n\");\n\tfprintf(stderr, \"\\t  -Xdict-size <dict-size>\\n\");\n\tfprintf(stderr, \"\\t\\tUse <dict-size> as the XZ dictionary size.  The\");\n\tfprintf(stderr, \" dictionary size\\n\\t\\tcan be specified as a\");\n\tfprintf(stderr, \" percentage of the block size, or as an\\n\\t\\t\");\n\tfprintf(stderr, \"absolute value.  The dictionary size must be less\");\n\tfprintf(stderr, \" than or equal\\n\\t\\tto the block size and 8192 bytes\");\n\tfprintf(stderr, \" or larger.  It must also be\\n\\t\\tstorable in the xz\");\n\tfprintf(stderr, \" header as either 2^n or as 2^n+2^(n+1).\\n\\t\\t\");\n\tfprintf(stderr, \"Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or\");\n\tfprintf(stderr, \" 32K, 16K, 8K\\n\\t\\tetc.\\n\");\n}\n\nstruct compressor xz_comp_ops = {\n\t.init = xz_init,\n\t.compress = xz_compress,\n\t.uncompress = xz_uncompress,\n\t.options = xz_options,\n\t.options_post = xz_options_post,\n\t.dump_options = xz_dump_options,\n\t.extract_options = xz_extract_options,\n\t.display_options = xz_display_options,\n\t.usage = xz_usage,\n\t.id = XZ_COMPRESSION,\n\t.name = \"xz\",\n\t.supported = 1\n};\n"
  },
  {
    "path": "src/stream/CMakeLists.txt",
    "content": "add_library(stream crc32.c tsfile.c)\n\ntarget_include_directories(stream PUBLIC ${INC}/stream)\ntarget_link_libraries(stream utils)"
  },
  {
    "path": "src/stream/crc32.c",
    "content": "#include <stdint.h>\n\nstatic const unsigned int crc_table[256] = {\n\t0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,\n\t0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,\n\t0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,\n\t0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,\n\t0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,\n\t0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,\n\t0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,\n\t0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,\n\t0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,\n\t0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,\n\t0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,\n\t0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,\n\t0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,\n\t0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,\n\t0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,\n\t0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,\n\t0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,\n\t0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,\n\t0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,\n\t0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,\n\t0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,\n\t0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,\n\t0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,\n\t0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,\n\t0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,\n\t0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,\n\t0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,\n\t0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,\n\t0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,\n\t0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,\n\t0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,\n\t0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,\n\t0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,\n\t0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,\n\t0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,\n\t0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,\n\t0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,\n\t0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,\n\t0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,\n\t0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,\n\t0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,\n\t0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,\n\t0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4\n};\n\nuint32_t str_crc32(const unsigned char *data, int len) {\n\tuint32_t crc = 0xffffffff;\n\tuint32_t i;\n\tfor (i = 0; i < len; i++)\n\t\tcrc = (crc << 8) ^ crc_table[((crc >> 24) ^ *data++) & 0xff];\n\treturn crc;\n}\n"
  },
  {
    "path": "src/stream/tsfile.c",
    "content": "/**\n * TS file Decryption\n * (C) 2020 the epk2extract authors\n **/\n\n/* Transport Stream Header (or 4-byte prefix) consists of 32-bit:\n\tSync byte\t\t\t\t\t\t8bit\t0x47\n\tTransport Error Indicator (TEI)\t1bit\tSet by demodulator if can't correct errors in the stream, to tell the demultiplexer that the packet\n\t\t\t\t\t\t\t\t\t\t\thas an uncorrectable error [11]\n\tPayload Unit Start Indicator\t1bit\t1 means start of PES data or PSI otherwise zero only.\n\tTransport Priority\t\t\t\t1bit\t1 means higher priority than other packets with the same PID.\n\tPID\t\t\t\t\t\t\t\t13bit\tPacket ID\n\tScrambling control\t\t\t\t2bit\t'00' = Not scrambled. The following per DVB spec:[12]\n\t\t\t\t\t\t\t\t\t\t\t'01' = Reserved for future use, '10' = Scrambled with even key, '11' = Scrambled with odd key\n\tAdaptation field exist\t\t\t2bit\t'01' = no adaptation fields, payload only, '10' = adaptation field only, '11' = adaptation field and payload\n\tContinuity counter\t\t\t\t4bit\tIncremented only when a payload is present (i.e., adaptation field exist is 01 or 11)[13]\n*/\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdbool.h>\n#include <string.h>\n#include <inttypes.h>\n#include <openssl/aes.h>\n\n#include <sys/stat.h>\n#include <unistd.h>\n\n#include \"util.h\"\n#include \"stream/crc32.h\"\n#include \"stream/tsfile.h\"\n\n\n#define TS_PACKET_SIZE 192\nstatic AES_KEY AESkey;\n\nstatic bool do_unwrap_func(const uint8_t unwrap_key[], const uint8_t aes_key[], uint8_t unwrapped_key[]) {\n\tputs(\"Wrapped key: \");\n\tfor (unsigned int i = 0; i < 24; i++){\n\t\tprintf(\"%02\" PRIX8, aes_key[i]);\n\t}\n\n\t// 8 bytes of 0xB7 (B7B7B7B7B7B7B7B7)\n\tconst uint8_t wrap_iv[8] = {0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7};\n\n\t// TODO: replace these deprecated functions\n\t// unwrap 'aes_key' with 'unwrap_key' into 'unwrapped_key'\n\tAES_set_decrypt_key(unwrap_key, 128, &AESkey);\n\tAES_unwrap_key(&AESkey, wrap_iv, unwrapped_key, aes_key, 24);\n\n\tuint8_t accum = 0;\n\n\tputs(\"\\nUnwrapped key: \");\n\tfor (unsigned int i = 0; i < 16; i++){\n\t\tprintf(\"%02\" PRIX8, unwrapped_key[i]);\n\n\t\t// Record any bits that are set\n\t\taccum |= unwrapped_key[i];\n\t}\n\tputchar('\\n');\n\n\t// If all bits were zero, return false\n\treturn (accum != 0);\n}\n\nstatic int setKey(char *keyPath) {\n\tint ret = -1;\n\n\tFILE *keyFile = fopen(keyPath, \"r\");\n\tif (keyFile == NULL) {\n\t\tfprintf(stderr, \"%s not found.\\n\", keyPath);\n\t\treturn ret;\n\t}\n\n\tstruct stat statBuf;\n\tif((ret=fstat(fileno(keyFile), &statBuf)) < 0){\n\t\tfprintf(stderr, \"setKey: stat failed\\n\");\n\t\treturn ret;\n\t}\n\n\tbool doUnwrap;\n\n\tswitch(statBuf.st_size){\n\t\tcase 16:\n\t\t\tprintf(\"=> Unwrapped AES-128 key detected\\n\");\n\t\t\tdoUnwrap = false;\n\t\t\tbreak;\n\t\tcase 24:\n\t\t\tprintf(\"=> Wrapped AES-128 key detected\\n\");\n\t\t\tdoUnwrap = true;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfprintf(stderr, \"Unknown or invalid key found (key size=%jd)\\n\", (intmax_t) statBuf.st_size);\n\t\t\treturn -1;\n\t}\n\tint keySz = statBuf.st_size;\n\n\tuint8_t aes_key[keySz];\n\tmemset(&aes_key, 0x00, keySz);\n\n\tint read = fread(&aes_key, keySz, 1, keyFile);\n\tfclose(keyFile);\n\tif(read != 1){\n\t\tfprintf(stderr, \"key read error\\n\");\n\t\treturn -1;\n\t}\n\n\tif(doUnwrap){\n\t\tuint8_t unwrapped_key[16];\n\t\tuint8_t unwrap_key[16];\n\t\t// set unwrap_key: 0x01, 0x02, 0x03, ... 0x0F\n\t\tfor (int i = 0; i < sizeof(unwrap_key); i++){\n\t\t\tunwrap_key[i] = i;\n\t\t\t//printf(\"%02\" PRIx8, unwrap_key[i]);\n\t\t}\n\t\tputchar('\\n');\n\n\t\tif (!do_unwrap_func(unwrap_key, aes_key, unwrapped_key)) {\n\t\t\t// If unwrapping failed, try alternative KEK from ww#8543\n\t\t\tputs(\"Failed to unwrap key; trying again with alternative key encryption key...\\n\");\n\t\t\tconst uint8_t unwrap_key2[16] = {0xb1, 0x52, 0x73, 0x3f, 0x68, 0x61, 0x3b, 0x6a, 0x40, 0x6c, 0x7a, 0xa4, 0xbe, 0x28, 0xb8, 0xb6};\n\t\t\tif (!do_unwrap_func(unwrap_key2, aes_key, unwrapped_key)) {\n\t\t\t\tputs(\"Failed to unwrap key\\n\");\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t\tAES_set_decrypt_key(unwrapped_key, 128, &AESkey);\n\t}\n\telse {\n\t\tAES_set_decrypt_key(aes_key, 128, &AESkey);\n\t}\n\n\treturn 0;\n}\n\n// minimum number of TS packets (sync bytes) that must be present\n#define MIN_TS_PACKETS 3\n\nuint8_t *findTsPacket(MFILE *tsFile, long offset){\n\tif(offset >= msize(tsFile)){\n\t\treturn NULL;\n\t}\n\tuint8_t *head;\n\tuint8_t *cur;\n\n\tint syncPackets;\n\n\tdo {\n\t\t// abort in case no valid sync is found in the first bytes of the file\n\t\tif(offset >= (TS_PACKET_SIZE * 2)){\n\t\t\treturn NULL;\n\t\t}\n\n\t\tsyncPackets = 0;\n\n\t\t// find initial sync position sequentially\n\t\tfor(head = mdata(tsFile, uint8_t) + offset;\n\t\t\tmoff(tsFile, head) < msize(tsFile) && *head != 0x47;\n\t\t\thead++\n\t\t);\n\n\t\t// EOF condition\n\t\tif(*head != 0x47) break;\n\n\t\t++syncPackets;\n\t\tcur = head;\n\n\t\t// found the initial sync. now check next packets\n\t\tfor(int i=0;\n\t\t\t//\n\t\t\tsyncPackets<MIN_TS_PACKETS\n\t\t\t&& moff (tsFile, cur) < msize(tsFile)\n\t\t\t&& cur[TS_PACKET_SIZE * i] == 0x47;\n\t\t\t//\n\t\t\tsyncPackets++,\n\t\t\tcur+=TS_PACKET_SIZE,\n\t\t\ti++);\n\n\t\t// increase offset to be able to find the correct sync in case a \"garbage\" sync was found\n\t\toffset = moff(tsFile, head) + 1;\n\t} while(syncPackets<MIN_TS_PACKETS);\n\n\tif(syncPackets < MIN_TS_PACKETS){\n\t\treturn NULL;\n\t}\n\n\treturn head;\n}\n\nvoid writeHeaders(FILE *outFile){\n\tuint8_t outBuf[TS_PACKET_SIZE];\n\n\t{ // Construct and write PAT\n\t\tmemset(outBuf, 0xFF, TS_PACKET_SIZE);\n\t\tuint8_t PAT[] = {\n\t\t\t0x47, 0x40, 0x00, 0x10, 0x00, 0x00, 0xB0, 0x0D,\n\t\t\t0x00, 0x06, 0xC7, 0x00, 0x00, 0x00, 0x01, 0xE0,\n\t\t\t0xB1, 0xA2, 0x89, 0x69, 0x78\n\t\t};\n\t\tmemcpy(outBuf, &PAT, sizeof(PAT));\n\t\tfwrite(outBuf, 1, TS_PACKET_SIZE - 4, outFile);\n\t}\n\n\t{ // Write empty PMT\n\t\tmemset(outBuf, 0xFF, TS_PACKET_SIZE);\n\t\tfwrite(outBuf, 1, TS_PACKET_SIZE - 4, outFile);\n\t}\n}\n\n\nstruct tables {\n\tint number[8192];\n\tunsigned char type[8192];\n\tint pcr_count[8192];\n};\n\n#define AUDIO_TYPE_MPEG2 0x04\n#define VIDEO_TYPE_H264 0x1B\n\nstatic inline uint32_t pack_pid(int pid){\n\treturn (0\n\t\t// reserved bits\n\t\t| 0x07 << 29\n\t\t// PID\n\t\t| ((pid & 0x1FFF) << 16)\n\t\t// reserved bits\n\t\t| 0x0F << 12\n\t) & 0xFFFFF;\n}\n\nvoid writePMT(struct tables *PIDs, FILE *outFile, struct tsfile_options *opts){\n\tint audio_stream_type = (opts->audio_stream_type == -1) ? AUDIO_TYPE_MPEG2 : opts->audio_stream_type;\n\tint video_stream_type = (opts->video_stream_type == -1) ? VIDEO_TYPE_H264 : opts->video_stream_type;\n\n\t// Gather information for PMT construction\n\tunsigned char stream_count = 0;\n\tfor (unsigned int i = 0; i < 8192; i++) {\n\t\t//Count video stream PIDs (0xE0-0xEF)\n\t\tif (PIDs->type[i] >= 0xE0 && PIDs->type[i] <= 0xEF) {\n\t\t\tstream_count++;\n\t\t}\n\t\t//Count audio stream PIDs (0xC0-0xDF)\n\t\telse if (PIDs->type[i] >= 0xC0 && PIDs->type[i] <= 0xDF) {\n\t\t\tstream_count++;\n\t\t}\n\t}\n\tunsigned char PMT_size = 21 + stream_count * 5;\n\n\tuint8_t outBuf[TS_PACKET_SIZE];\n\tmemset(outBuf, 0xFF, TS_PACKET_SIZE);\n\n\t// Fill PMT\n\tuint8_t PMT[TS_PACKET_SIZE - 4];\n\tmemset(PMT, 0xFF, TS_PACKET_SIZE - 4);\n\n\tconst uint8_t PMT_header[17] = {\n\t\t/** 0x0: Transport header (TS) **/\n\t\t0x47, // sync byte\n\t\t0x40, // PUSI flag\n\t\t0xB1, 0x10,\n\t\t/** 0x4: PSI **/\n\t\t0x00, // pointer field\n\t\t/** 0x5: table header **/\n\t\t0x02, // program_map_section\n\t\t0xB0,\n\t\t0x00,\t\t\t\t// section length in bytes including crc\n\t\t/** 0x8: table syntax data **/\n\t\t0x00, 0x01,\t\t\t// program number\n\t\t0xC1, 0x00, 0x00,\n\t\t/** 0xD: PMT data **/\n\t\t0xE4, 0x7E,\t\t\t// PCR PID\n\t\t0xF0, 0x00\t\t\t// Program info length\n\t\t/** 0x11 **/\n\t};\n\tmemcpy(PMT, PMT_header, sizeof(PMT_header));\n\tPMT[7] = 13 + stream_count * 5;\n\n\tuint32_t pmt_data;\n\n\tstream_count = 0;\n\tfor (unsigned int i = 0; i < 8192; i++){\n\t\tuint32_t packed_pid = pack_pid(i);\n\t\tif (PIDs->number[i] > 0) {\n\t\t\tprintf(\"PID %X : %d Type: %hhX PCRs: %X\\n\", i, PIDs->number[i], PIDs->type[i], (unsigned int) PIDs->pcr_count[i]);\n\t\t\tif (PIDs->pcr_count[i] > 0) {\t// Set PCR PID\n\t\t\t\tpmt_data = (0\n\t\t\t\t\t| (packed_pid << 12)\n\t\t\t\t\t// program info length (0 for now)\n\t\t\t\t\t| 0 & 0xFFF\n\t\t\t\t);\n\n\t\t\t\tPMT[13] = (pmt_data >> 24) & 0xFF;\n\t\t\t\tPMT[14] = (pmt_data >> 16) & 0xFF;\n\t\t\t\tPMT[15] = (pmt_data >>  8) & 0xFF;\n\t\t\t\tPMT[16] = (pmt_data >>  0) & 0xFF;\n\t\t\t}\n\n\t\t\tuint32_t es_data = (0\n\t\t\t\t| (packed_pid << 12)\n\t\t\t\t// ES info length (0 for now)\n\t\t\t\t| 0 & 0xFFF\n\t\t\t);\n\n\t\t\t//Set video stream data in PMT\n\t\t\tif (PIDs->type[i] >= 0xE0 && PIDs->type[i] <= 0xEF) {\n\t\t\t\tPMT[17 + stream_count * 5] = video_stream_type; // stream type\n\t\t\t\tPMT[18 + stream_count * 5] = (es_data >> 24) & 0xFF;\n\t\t\t\tPMT[19 + stream_count * 5] = (es_data >> 16) & 0xFF;\n\t\t\t\tPMT[20 + stream_count * 5] = (es_data >>  8) & 0xFF;\n\t\t\t\tPMT[21 + stream_count * 5] = (es_data >>  0) & 0xF;\n\t\t\t\tstream_count++;\n\t\t\t}\n\t\t\t//Set audio stream data in PMT\n\t\t\telse if (PIDs->type[i] >= 0xC0 && PIDs->type[i] <= 0xDF) {\n\t\t\t\tPMT[17 + stream_count * 5] = audio_stream_type; // stream type\n\t\t\t\tPMT[18 + stream_count * 5] = (es_data >> 24) & 0xFF;\n\t\t\t\tPMT[19 + stream_count * 5] = (es_data >> 16) & 0xFF;\n\t\t\t\tPMT[20 + stream_count * 5] = (es_data >>  8) & 0xFF;\n\t\t\t\tPMT[21 + stream_count * 5] = (es_data >>  0) & 0xF;\n\t\t\t\tstream_count++;\n\t\t\t}\n\t\t}\n\t}\n\t// Set CRC32\n\t// A checksum of the entire table\n\t// excluding the pointer field, pointer filler bytes (aka none)\n\t// and the trailing CRC32.\n\tuint32_t crc = str_crc32(&PMT[5], PMT[7] - 1);\n\tPMT[PMT_size - 4] = (crc >> 24) & 0xFF;\n\tPMT[PMT_size - 3] = (crc >> 16) & 0xFF;\n\tPMT[PMT_size - 2] = (crc >> 8) & 0xFF;\n\tPMT[PMT_size - 1] = crc & 0xFF;\n\tmemcpy(outBuf, PMT, sizeof(PMT));\n\n\tfseek(outFile, 0xBC, SEEK_SET);\n\tfwrite(outBuf, 1, TS_PACKET_SIZE, outFile);\n}\n\nvoid processTsPacket(uint8_t *packet, struct tables *PIDs, FILE *outFile){\n\tuint8_t outBuf[TS_PACKET_SIZE];\n\n\t// data offset\n\tint offset = 4;\n\n\t// Transport scrambling control\n\tint tsc = packet[3] & 0xC0;\n\t// either 0x20 or 0x30\n\tint have_adapt_field = (packet[3] & 0x30) > 0x10;\n\t// either 0x10 or 0x30\n\tint have_payload_field = (packet[3] & 0x30) != 0x20;\n\tint pid = (0\n\t\t| ((packet[1] & 0x1F) << 8)\n\t\t| packet[2]\n\t);\n\n\tif(!have_payload_field){\n\t\treturn;\n\t}\n\n\tif (\n\t\t// LG Netcast writes even/odd DVB-CSA flag, even tho the key is fixed\n\t\ttsc == 0x80 || tsc == 0xC0\n\t\t// WebOS uses the \"reserved\" flag instead\n\t\t|| tsc == 0x40\n\t) {\n\t\t// packet is encrypted, so we copy the original (readonly) for modifications\n\t\tmemcpy(outBuf, packet, TS_PACKET_SIZE);\n\t\t// now set the pointer to the copy\n\t\tpacket = &outBuf[0];\n\n\t\tif(have_adapt_field){\n\t\t\toffset += (packet[4] + 1);\t// adaption field length + sizeof length field\n\t\t}\n\n\t\tpacket[3] &= ~0xC0;\t// remove scrambling bits\n\t\tif (offset > TS_PACKET_SIZE){\n\t\t\t//application will crash without this check when file is corrupted\n\t\t\toffset = TS_PACKET_SIZE;\n\t\t}\n\n\t\t// NOTE: 4 seems to be custom LG padding, excluded from AES\n\t\tint data_length = TS_PACKET_SIZE - offset - 4;\n\t\tunsigned blocks = data_length / AES_BLOCK_SIZE;\n\t\tfor (unsigned int i = 0; i < blocks; i++){\n\t\t\t// in-place decrypt (ECB)\n\t\t\tAES_decrypt(\n\t\t\t\t&packet[offset + i * AES_BLOCK_SIZE],\n\t\t\t\t&packet[offset + i * AES_BLOCK_SIZE],\n\t\t\t\t&AESkey);\n\t\t}\n\t};\n\n\t// Search PCR\n\tif (have_adapt_field){\n\t\tif (packet[5] & 0x10){\t// check if PCR exists\n\t\t\tPIDs->pcr_count[pid]++;\n\t\t}\n\t}\n\t// Count PES packets only\n\t// check PES start code prefix\n\tif(packet[offset + 0] == 0\n\t&& packet[offset + 1] == 0\n\t&& packet[offset + 2] == 1\n\t){\n\t\tPIDs->number[pid]++;\n\t\t// stream ID. Examples: Audio streams (0xC0-0xDF), Video streams (0xE0-0xEF)\n\t\tPIDs->type[pid] = packet[offset + 3];\n\t}\n\tfwrite(packet, 1, TS_PACKET_SIZE, outFile);\n}\n\nvoid convertSTR2TS_internal(char *inFilename, char *outFilename, struct tsfile_options *opts) {\n\tMFILE *inFile = mopen(inFilename, O_RDONLY);\n\tif (inFile == NULL) {\n\t\tprintf(\"Can't open file %s\\n\", inFilename);\n\t\treturn;\n\t}\n\n\tstruct tables PIDs;\n\tmemset(&PIDs, 0, sizeof(PIDs));\n\n\tdo {\n\t\tconst char *mode = (opts->append) ? \"a+b\" : \"wb\";\n\t\tFILE *outFile = fopen(outFilename, mode);;\n\n\t\tif (outFile == NULL) {\n\t\t\tfprintf(stderr, \"Can't open file %s\\n\", outFilename);\n\t\t\tbreak;\n\t\t}\n\n\t\tdo {\n\t\t\tuint8_t *packet = findTsPacket(inFile, 0);\n\t\t\tif(packet == NULL){\n\t\t\t\tfprintf(stderr, \"Could not find sync\\n\");\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\twriteHeaders(outFile);\n\n\t\t\tlong offset;\n\t\t\tfor(;\n\t\t\t\t(offset=moff(inFile, packet)) < msize(inFile)\n\t\t\t\t&& offset + TS_PACKET_SIZE < msize(inFile)\n\t\t\t\t;\n\t\t\t\tpacket += TS_PACKET_SIZE\n\t\t\t){\n\t\t\t\tif(packet[0] != 0x47){\n\t\t\t\t\tfprintf(stderr, \"\\nLost sync at offset %\" PRIx64 \"\\n\", offset);\n\t\t\t\t\tpacket = findTsPacket(inFile, offset);\n\t\t\t\t}\n\t\t\t\tif(packet == NULL){\n\t\t\t\t\tfprintf(stderr, \"error: lost sync\\n\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tprocessTsPacket(packet, &PIDs, outFile);\n\t\t\t}\n\t\t} while(0);\n\n\t\twritePMT(&PIDs, outFile, opts);\n\t\tfclose(outFile);\n\t} while(0);\n\tmclose(inFile);\n}\n\nvoid convertSTR2TS(char *inFilename, struct tsfile_options *opts) {\n\tchar *baseDir = my_dirname(inFilename);\n\tchar *keyPath;\n\n\tasprintf(&keyPath, \"%s/dvr\", baseDir);\n\tif (0 != setKey(keyPath)){\n\t\tfree(keyPath);\n\t\terr_exit(\"Load DVR Key-file failed for %s/dvr\\n\", baseDir);\n\t}\n\tfree(keyPath);\n\n\tchar *baseName = my_basename(inFilename);\n\tchar *outFilename;\n\tasprintf(&outFilename, \"%s/%s.ts\", baseDir, baseName);\n\n\tprintf(\"Output File: %s\\n\", outFilename);\n\tconvertSTR2TS_internal(inFilename, outFilename, opts);\n\n\tfree(baseName);\n\tfree(baseDir);\n}\n\nvoid processPIF(const char *filename, char *dest_file) {\n\tFILE *file = fopen(filename, \"r\");\n\tif (file == NULL) {\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\t}\n\n\tstruct stat statBuf;\n\tif(stat(filename, &statBuf) < 0){\n\t\terr_exit(\"stat() failed for %s\\n\", filename);\n\t}\n\n\tsize_t filesize = statBuf.st_size;\n\n\tchar *baseDir = my_dirname(filename);\n\n\tchar *keyPath;\n\tasprintf(&keyPath, \"%s/dvr\", baseDir);\n\n\tif (0 != setKey(keyPath)){\n\t\tfree(keyPath);\n\t\terr_exit(\"Load DVR Key-file failed for %s/dvr\\n\", baseDir);\n\t}\n\tfree(keyPath);\n\n\tint append = 0;\n\tchar *buffer = calloc(1, filesize);\n\tint read = fread(buffer, 1, filesize, file);\n\tif (read == filesize) {\n\t\tint i;\n\t\tfor (i = 0; i < (filesize - 5); i++) {\n\t\t\tif (!memcmp(&buffer[i], \"/mnt/\", 5) && !memcmp(&buffer[i + strlen(&buffer[i]) - 3], \"STR\", 3)) {\n\n\t\t\t\tchar *strName = strrchr(&buffer[i], '/') + 1;\n\t\t\t\tchar *filePath;\n\t\t\t\tasprintf(&filePath, \"%s/%s\", baseDir, strName);\n\n\t\t\t\tprintf(\"Converting file: %s -> %s\\n\", filePath, dest_file);\n\n\t\t\t\tstruct tsfile_options opts = {\n\t\t\t\t\t// $TODO: add a way to specify these\n\t\t\t\t\t.video_stream_type = -1,\n\t\t\t\t\t.audio_stream_type = -1,\n\t\t\t\t\t.append = append\n\t\t\t\t};\n\n\t\t\t\tconvertSTR2TS_internal(filePath, dest_file, &opts);\n\t\t\t\tfree(filePath);\n\n\t\t\t\tappend = 1;\n\t\t\t}\n\t\t}\n\t}\n\tfclose(file);\n\tfree(buffer);\n\n\tfree(baseDir);\n}\n"
  },
  {
    "path": "src/symfile.c",
    "content": "/*\n * Copyright (c) 2011 Roman Tokarev <roman.s.tokarev@gmail.com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the author nor the names of any co-contributors\n * may be used to endorse or promote products derived from this software\n * without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\n * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\n * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <symfile.h>\n\n#include <fcntl.h>\n#include <stdio.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#define MAGIC 0xB12791EE\n\nstruct symfile_header {\n\tuint32_t magic;\n\tuint32_t unknown;\n\tuint32_t size;\n\tuint32_t n_symbols;\n\tuint32_t tail_size;\n}__attribute__((packed));\n\nstruct sym_table sym_table = {\n\t.n_symbols = 0,\n\t.sym_entry = NULL,\n\t.hash = NULL,\n\t.n_dwarf_lst = 0,\n\t.dwarf_lst = NULL,\n\t.dwarf_data = NULL,\n\t.sym_name = NULL\n};\n\nint symfile_load(const char *fname) {\n\tint fd = -1;\n\tstruct stat st_buf;\n\tvoid *p;\n\tstruct symfile_header *header;\n\tuint32_t *has_hash, *has_dwarf;\n\tuint32_t dwarf_data_size = 0;\n\n\tfd = open(fname, O_RDONLY);\n\tif (fd == -1) {\n\t\tfprintf(stderr, \"can't open `%s': %m\\n\", fname);\n\n\t\treturn -1;\n\t}\n\n\tif (fstat(fd, &st_buf) != 0) {\n\t\tfprintf(stderr, \"fstat for `%s' is failed: %m\\n\", fname);\n\n\t\treturn -1;\n\t}\n\n\tp = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);\n\theader = p;\n\tp += sizeof(*header);\n\tif (header == NULL) {\n\t\tfprintf(stderr, \"can't mmap `%s': %m\\n\", fname);\n\n\t\treturn -1;\n\t}\n\n\tif (header->magic != MAGIC) {\n\t\t//fprintf(stderr, \"bad magic 0x%x from `%s'\\n\", header->magic, fname);\n\t\treturn -1;\n\t}\n\n\tif ((header->size + sizeof(*header)) != (uint32_t) st_buf.st_size) {\n\t\tfprintf(stderr, \"bad file `%s' size: %zu, expected size: %lu\\n\", fname,\n\t\t\t\tst_buf.st_size, header->size + sizeof(*header));\n\n\t\treturn -1;\n\t}\n\n\tif ((header->tail_size + sizeof(struct sym_entry) * header->n_symbols)\t!= header->size) {\n\t\tfprintf(stderr, \"file `%s' is broken\\n\", fname);\n\t\treturn -1;\n\t}\n\n\tsym_table.n_symbols = header->n_symbols;\n\tsym_table.sym_entry = p;\n\tp += sizeof(sym_table.sym_entry[0]) * sym_table.n_symbols;\n\n\thas_hash = p;\n\tp += sizeof(*has_hash);\n\tif (*has_hash != 2 && *has_hash != 0) {\n\t\tfprintf(stderr, \"unsupported file `%s' format (unexpected has_hash 0x%x)\\n\", fname, *has_hash);\n\t\treturn -1;\n\t}\n\n\tif (*has_hash == 2) {\n\t\tsym_table.hash = p;\n\t\tp += sizeof(sym_table.hash[0]) * ((sym_table.n_symbols + 1) & (~0 - 1));\n\t}\n\n\thas_dwarf = p;\n\tp += sizeof(*has_dwarf);\n\n\tif (*has_dwarf == 1) {\n\t\tsym_table.n_dwarf_lst = *(uint32_t *) p;\n\t\tp += sizeof(sym_table.n_dwarf_lst);\n\t\tdwarf_data_size = *(uint32_t *) p;\n\t\tp += sizeof(dwarf_data_size);\n\t\tsym_table.dwarf_lst = p;\n\t\tp += sizeof(sym_table.dwarf_lst[0]) * sym_table.n_dwarf_lst;\n\t\tsym_table.dwarf_data = p;\n\t\tp += dwarf_data_size;\n\t\tsym_table.sym_name = p;\n\t} else {\n\t\tsym_table.sym_name = (char *)has_dwarf;\n\t}\n\n\tprintf(\"`%s' has been successfully loaded\\n\", fname);\n\n\treturn 0;\n}\n\nuint32_t symfile_addr_by_name(const char *name) {\n\tunsigned i = 0;\n\tfor (i = 0; i < sym_table.n_symbols; ++i) {\n\t\tchar *sym_name = sym_table.sym_name\t+ sym_table.sym_entry[i].sym_name_off;\n\n\t\tif (strcmp(sym_name, name) == 0)\n\t\t\treturn sym_table.sym_entry[i].addr;\n\t}\n\n\treturn 0;\n}\n\nuint32_t symfile_n_symbols() {\n\treturn sym_table.n_symbols;\n}\n\nvoid symfile_write_idc(const char *fname) {\n\n\tFILE *outfile = fopen(fname, \"w\");\n\n\tfprintf(outfile, \"%s\\n\\n\", \"#include <idc.idc>\");\n\tfprintf(outfile, \"%s\\n\", \"static main() {\");\n\n\tunsigned i = 0;\n\tfor (i = 0; i < sym_table.n_symbols; ++i) {\n\t\t\tchar *sym_name = sym_table.sym_name\n\t\t\t\t\t+ sym_table.sym_entry[i].sym_name_off;\n\n\t\t\tuint32_t addr = sym_table.sym_entry[i].addr;\n\t\t\tuint32_t end = sym_table.sym_entry[i].end;\n\n\t\t\t//printf(\"%s: %x...%x\\n\", sym_name, addr, end);\n\n\t\t\tfprintf(outfile, \"MakeNameEx( 0x%x, \\\"%s\\\", SN_NOWARN | SN_CHECK);\\n\", addr, sym_name);\n\n\t\t\tfprintf(outfile, \"if(SegName(0x%x)==\\\".text\\\") {\\n\", addr);\n\t\t\tfprintf(outfile, \"   MakeCode(0x%x);\\n\", addr);\n\t\t\tfprintf(outfile, \"   MakeFunction(0x%x, 0x%x);\\n\", addr, end);\n\t\t\tfprintf(outfile, \"};\\n\");\n\n\t}\n\n\tfprintf(outfile, \"%s\\n\", \"}\");\n\n\tfclose(outfile);\n\n\t//printf(\"n_dwarf_lst: %d\\n\", sym_table.n_dwarf_lst);\n\t//printf(\"dwarf_lst.d1: %d\\n\", sym_table.dwarf_lst->d1);\n\t//printf(\"dwarf_lst.d2: %d\\n\", sym_table.dwarf_lst->d2);\n\n\t//hexdump(sym_table.dwarf_data, 15000);\n\n}\n\n\nconst char *symfile_name_by_addr(uint32_t addr) {\n\tint i = 0;\n\tfor (i = sym_table.n_symbols - 1; i >= 0; --i) {\n\t\tif (sym_table.sym_entry[i].addr <= addr && sym_table.sym_entry[i].end > addr)\n\t\t\treturn sym_table.sym_name + sym_table.sym_entry[i].sym_name_off;\n\t}\n\n\treturn NULL;\n}\n"
  },
  {
    "path": "src/thpool.c",
    "content": "/* ********************************\n * Author:       Johan Hanssen Seferidis\n * License:\t     MIT\n * Description:  Library providing a threading pool where you can add\n *               work. For usage, check the thpool.h file or README.md\n *\n *//** @file thpool.h *//*\n *\n ********************************/\n\n#include <unistd.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <pthread.h>\n#include <errno.h>\n#include <time.h>\n#if defined(__linux__)\n#include <sys/prctl.h>\n#endif\n#include \"thpool.h\"\n\n#ifdef THPOOL_DEBUG\n#define THPOOL_DEBUG 1\n#else\n#define THPOOL_DEBUG 0\n#endif\n\nstatic volatile int threads_keepalive;\nstatic volatile int threads_on_hold;\n\n\n\n/* ========================== STRUCTURES ============================ */\n\n\n/* Binary semaphore */\ntypedef struct bsem {\n\tpthread_mutex_t mutex;\n\tpthread_cond_t   cond;\n\tint v;\n} bsem;\n\n\n/* Job */\ntypedef struct job{\n\tstruct job*  prev;                   /* pointer to previous job   */\n\tvoid   (*function)(void* arg);       /* function pointer          */\n\tvoid*  arg;                          /* function's argument       */\n} job;\n\n\n/* Job queue */\ntypedef struct jobqueue{\n\tpthread_mutex_t rwmutex;             /* used for queue r/w access */\n\tjob  *front;                         /* pointer to front of queue */\n\tjob  *rear;                          /* pointer to rear  of queue */\n\tbsem *has_jobs;                      /* flag as binary semaphore  */\n\tint   len;                           /* number of jobs in queue   */\n} jobqueue;\n\n\n/* Thread */\ntypedef struct thread{\n\tint       id;                        /* friendly id               */\n\tpthread_t pthread;                   /* pointer to actual thread  */\n\tstruct thpool_* thpool_p;            /* access to thpool          */\n} thread;\n\n\n/* Threadpool */\ntypedef struct thpool_{\n\tthread**   threads;                  /* pointer to threads        */\n\tvolatile int num_threads_alive;      /* threads currently alive   */\n\tvolatile int num_threads_working;    /* threads currently working */\n\tpthread_mutex_t  thcount_lock;       /* used for thread count etc */\n\tpthread_cond_t  threads_all_idle;    /* signal to thpool_wait     */\n\tjobqueue*  jobqueue_p;               /* pointer to the job queue  */\n} thpool_;\n\n\n\n\n\n/* ========================== PROTOTYPES ============================ */\n\n\nstatic int  thread_init(thpool_* thpool_p, struct thread** thread_p, int id);\nstatic void* thread_do(struct thread* thread_p);\nstatic void  thread_hold();\nstatic void  thread_destroy(struct thread* thread_p);\n\nstatic int   jobqueue_init(thpool_* thpool_p);\nstatic void  jobqueue_clear(thpool_* thpool_p);\nstatic void  jobqueue_push(thpool_* thpool_p, struct job* newjob_p);\nstatic struct job* jobqueue_pull(thpool_* thpool_p);\nstatic void  jobqueue_destroy(thpool_* thpool_p);\n\nstatic void  bsem_init(struct bsem *bsem_p, int value);\nstatic void  bsem_reset(struct bsem *bsem_p);\nstatic void  bsem_post(struct bsem *bsem_p);\nstatic void  bsem_post_all(struct bsem *bsem_p);\nstatic void  bsem_wait(struct bsem *bsem_p);\n\n\n\n\n\n/* ========================== THREADPOOL ============================ */\n\n\n/* Initialise thread pool */\nstruct thpool_* thpool_init(int num_threads){\n\n\tthreads_on_hold   = 0;\n\tthreads_keepalive = 1;\n\n\tif (num_threads < 0){\n\t\tnum_threads = 0;\n\t}\n\n\t/* Make new thread pool */\n\tthpool_* thpool_p;\n\tthpool_p = (struct thpool_*)malloc(sizeof(struct thpool_));\n\tif (thpool_p == NULL){\n\t\tfprintf(stderr, \"thpool_init(): Could not allocate memory for thread pool\\n\");\n\t\treturn NULL;\n\t}\n\tthpool_p->num_threads_alive   = 0;\n\tthpool_p->num_threads_working = 0;\n\n\t/* Initialise the job queue */\n\tif (jobqueue_init(thpool_p) == -1){\n\t\tfprintf(stderr, \"thpool_init(): Could not allocate memory for job queue\\n\");\n\t\tfree(thpool_p);\n\t\treturn NULL;\n\t}\n\n\t/* Make threads in pool */\n\tthpool_p->threads = (struct thread**)malloc(num_threads * sizeof(struct thread *));\n\tif (thpool_p->threads == NULL){\n\t\tfprintf(stderr, \"thpool_init(): Could not allocate memory for threads\\n\");\n\t\tjobqueue_destroy(thpool_p);\n\t\tfree(thpool_p->jobqueue_p);\n\t\tfree(thpool_p);\n\t\treturn NULL;\n\t}\n\n\tpthread_mutex_init(&(thpool_p->thcount_lock), NULL);\n\tpthread_cond_init(&thpool_p->threads_all_idle, NULL);\n\n\t/* Thread init */\n\tint n;\n\tfor (n=0; n<num_threads; n++){\n\t\tthread_init(thpool_p, &thpool_p->threads[n], n);\n\t\tif (THPOOL_DEBUG)\n\t\t\tprintf(\"THPOOL_DEBUG: Created thread %d in pool \\n\", n);\n\t}\n\n\t/* Wait for threads to initialize */\n\twhile (thpool_p->num_threads_alive != num_threads) {}\n\n\treturn thpool_p;\n}\n\n\n/* Add work to the thread pool */\nint thpool_add_work(thpool_* thpool_p, void (*function_p)(void*), void* arg_p){\n\tjob* newjob;\n\n\tnewjob=(struct job*)malloc(sizeof(struct job));\n\tif (newjob==NULL){\n\t\tfprintf(stderr, \"thpool_add_work(): Could not allocate memory for new job\\n\");\n\t\treturn -1;\n\t}\n\n\t/* add function and argument */\n\tnewjob->function=function_p;\n\tnewjob->arg=arg_p;\n\n\t/* add job to queue */\n\tpthread_mutex_lock(&thpool_p->jobqueue_p->rwmutex);\n\tjobqueue_push(thpool_p, newjob);\n\tpthread_mutex_unlock(&thpool_p->jobqueue_p->rwmutex);\n\n\treturn 0;\n}\n\n\n/* Wait until all jobs have finished */\nvoid thpool_wait(thpool_* thpool_p){\n\tpthread_mutex_lock(&thpool_p->thcount_lock);\n\twhile (thpool_p->jobqueue_p->len || thpool_p->num_threads_working) {\n\t\tpthread_cond_wait(&thpool_p->threads_all_idle, &thpool_p->thcount_lock);\n\t}\n\tpthread_mutex_unlock(&thpool_p->thcount_lock);\n}\n\n\n/* Destroy the threadpool */\nvoid thpool_destroy(thpool_* thpool_p){\n\t/* No need to destory if it's NULL */\n\tif (thpool_p == NULL) return ;\n\n\tvolatile int threads_total = thpool_p->num_threads_alive;\n\n\t/* End each thread 's infinite loop */\n\tthreads_keepalive = 0;\n\n\t/* Give one second to kill idle threads */\n\tdouble TIMEOUT = 1.0;\n\ttime_t start, end;\n\tdouble tpassed = 0.0;\n\ttime (&start);\n\twhile (tpassed < TIMEOUT && thpool_p->num_threads_alive){\n\t\tbsem_post_all(thpool_p->jobqueue_p->has_jobs);\n\t\ttime (&end);\n\t\ttpassed = difftime(end,start);\n\t}\n\n\t/* Poll remaining threads */\n\twhile (thpool_p->num_threads_alive){\n\t\tbsem_post_all(thpool_p->jobqueue_p->has_jobs);\n\t\tsleep(1);\n\t}\n\n\t/* Job queue cleanup */\n\tjobqueue_destroy(thpool_p);\n\tfree(thpool_p->jobqueue_p);\n\n\t/* Deallocs */\n\tint n;\n\tfor (n=0; n < threads_total; n++){\n\t\tthread_destroy(thpool_p->threads[n]);\n\t}\n\tfree(thpool_p->threads);\n\tfree(thpool_p);\n}\n\n\n/* Pause all threads in threadpool */\nvoid thpool_pause(thpool_* thpool_p) {\n\tint n;\n\tfor (n=0; n < thpool_p->num_threads_alive; n++){\n\t\tpthread_kill(thpool_p->threads[n]->pthread, SIGUSR1);\n\t}\n}\n\n\n/* Resume all threads in threadpool */\nvoid thpool_resume(thpool_* thpool_p) {\n\tthreads_on_hold = 0;\n}\n\n\n\n\n\n/* ============================ THREAD ============================== */\n\n\n/* Initialize a thread in the thread pool\n *\n * @param thread        address to the pointer of the thread to be created\n * @param id            id to be given to the thread\n * @return 0 on success, -1 otherwise.\n */\nstatic int thread_init (thpool_* thpool_p, struct thread** thread_p, int id){\n\n\t*thread_p = (struct thread*)malloc(sizeof(struct thread));\n\tif (thread_p == NULL){\n\t\tfprintf(stderr, \"thread_init(): Could not allocate memory for thread\\n\");\n\t\treturn -1;\n\t}\n\n\t(*thread_p)->thpool_p = thpool_p;\n\t(*thread_p)->id       = id;\n\n\tpthread_create(&(*thread_p)->pthread, NULL, (void *)thread_do, (*thread_p));\n\tpthread_detach((*thread_p)->pthread);\n\treturn 0;\n}\n\n\n/* Sets the calling thread on hold */\nstatic void thread_hold () {\n\tthreads_on_hold = 1;\n\twhile (threads_on_hold){\n\t\tsleep(1);\n\t}\n}\n\n\n/* What each thread is doing\n*\n* In principle this is an endless loop. The only time this loop gets interuppted is once\n* thpool_destroy() is invoked or the program exits.\n*\n* @param  thread        thread that will run this function\n* @return nothing\n*/\nstatic void* thread_do(struct thread* thread_p){\n\n\t/* Set thread name for profiling and debuging */\n\tchar thread_name[128] = {0};\n\tsprintf(thread_name, \"thread-pool-%d\", thread_p->id);\n\n#if defined(__linux__)\n\t/* Use prctl instead to prevent using _GNU_SOURCE flag and implicit declaration */\n\tprctl(PR_SET_NAME, thread_name);\n#elif defined(__APPLE__) && defined(__MACH__)\n\tpthread_setname_np(thread_name);\n#else\n\tfprintf(stderr, \"thread_do(): pthread_setname_np is not supported on this system\");\n#endif\n\n\t/* Assure all threads have been created before starting serving */\n\tthpool_* thpool_p = thread_p->thpool_p;\n\n\t/* Register signal handler */\n\tstruct sigaction act;\n\tsigemptyset(&act.sa_mask);\n\tact.sa_flags = 0;\n\tact.sa_handler = thread_hold;\n\tif (sigaction(SIGUSR1, &act, NULL) == -1) {\n\t\tfprintf(stderr, \"thread_do(): cannot handle SIGUSR1\");\n\t}\n\n\t/* Mark thread as alive (initialized) */\n\tpthread_mutex_lock(&thpool_p->thcount_lock);\n\tthpool_p->num_threads_alive += 1;\n\tpthread_mutex_unlock(&thpool_p->thcount_lock);\n\n\twhile(threads_keepalive){\n\n\t\tbsem_wait(thpool_p->jobqueue_p->has_jobs);\n\n\t\tif (threads_keepalive){\n\n\t\t\tpthread_mutex_lock(&thpool_p->thcount_lock);\n\t\t\tthpool_p->num_threads_working++;\n\t\t\tpthread_mutex_unlock(&thpool_p->thcount_lock);\n\n\t\t\t/* Read job from queue and execute it */\n\t\t\tvoid (*func_buff)(void* arg);\n\t\t\tvoid* arg_buff;\n\t\t\tjob* job_p;\n\t\t\tpthread_mutex_lock(&thpool_p->jobqueue_p->rwmutex);\n\t\t\tjob_p = jobqueue_pull(thpool_p);\n\t\t\tpthread_mutex_unlock(&thpool_p->jobqueue_p->rwmutex);\n\t\t\tif (job_p) {\n\t\t\t\tfunc_buff = job_p->function;\n\t\t\t\targ_buff  = job_p->arg;\n\t\t\t\tfunc_buff(arg_buff);\n\t\t\t\tfree(job_p);\n\t\t\t}\n\n\t\t\tpthread_mutex_lock(&thpool_p->thcount_lock);\n\t\t\tthpool_p->num_threads_working--;\n\t\t\tif (!thpool_p->num_threads_working) {\n\t\t\t\tpthread_cond_signal(&thpool_p->threads_all_idle);\n\t\t\t}\n\t\t\tpthread_mutex_unlock(&thpool_p->thcount_lock);\n\n\t\t}\n\t}\n\tpthread_mutex_lock(&thpool_p->thcount_lock);\n\tthpool_p->num_threads_alive --;\n\tpthread_mutex_unlock(&thpool_p->thcount_lock);\n\n\treturn NULL;\n}\n\n\n/* Frees a thread  */\nstatic void thread_destroy (thread* thread_p){\n\tfree(thread_p);\n}\n\n\n\n\n\n/* ============================ JOB QUEUE =========================== */\n\n\n/* Initialize queue */\nstatic int jobqueue_init(thpool_* thpool_p){\n\n\tthpool_p->jobqueue_p = (struct jobqueue*)malloc(sizeof(struct jobqueue));\n\tif (thpool_p->jobqueue_p == NULL){\n\t\treturn -1;\n\t}\n\tthpool_p->jobqueue_p->len = 0;\n\tthpool_p->jobqueue_p->front = NULL;\n\tthpool_p->jobqueue_p->rear  = NULL;\n\n\tthpool_p->jobqueue_p->has_jobs = (struct bsem*)malloc(sizeof(struct bsem));\n\tif (thpool_p->jobqueue_p->has_jobs == NULL){\n\t\treturn -1;\n\t}\n\n\tpthread_mutex_init(&(thpool_p->jobqueue_p->rwmutex), NULL);\n\tbsem_init(thpool_p->jobqueue_p->has_jobs, 0);\n\n\treturn 0;\n}\n\n\n/* Clear the queue */\nstatic void jobqueue_clear(thpool_* thpool_p){\n\n\twhile(thpool_p->jobqueue_p->len){\n\t\tfree(jobqueue_pull(thpool_p));\n\t}\n\n\tthpool_p->jobqueue_p->front = NULL;\n\tthpool_p->jobqueue_p->rear  = NULL;\n\tbsem_reset(thpool_p->jobqueue_p->has_jobs);\n\tthpool_p->jobqueue_p->len = 0;\n\n}\n\n\n/* Add (allocated) job to queue\n *\n * Notice: Caller MUST hold a mutex\n */\nstatic void jobqueue_push(thpool_* thpool_p, struct job* newjob){\n\n\tnewjob->prev = NULL;\n\n\tswitch(thpool_p->jobqueue_p->len){\n\n\t\tcase 0:  /* if no jobs in queue */\n\t\t\t\t\tthpool_p->jobqueue_p->front = newjob;\n\t\t\t\t\tthpool_p->jobqueue_p->rear  = newjob;\n\t\t\t\t\tbreak;\n\n\t\tdefault: /* if jobs in queue */\n\t\t\t\t\tthpool_p->jobqueue_p->rear->prev = newjob;\n\t\t\t\t\tthpool_p->jobqueue_p->rear = newjob;\n\n\t}\n\tthpool_p->jobqueue_p->len++;\n\n\tbsem_post(thpool_p->jobqueue_p->has_jobs);\n}\n\n\n/* Get first job from queue(removes it from queue)\n *\n * Notice: Caller MUST hold a mutex\n */\nstatic struct job* jobqueue_pull(thpool_* thpool_p){\n\n\tjob* job_p;\n\tjob_p = thpool_p->jobqueue_p->front;\n\n\tswitch(thpool_p->jobqueue_p->len){\n\n\t\tcase 0:  /* if no jobs in queue */\n\t\t  \t\t\tbreak;\n\n\t\tcase 1:  /* if one job in queue */\n\t\t\t\t\tthpool_p->jobqueue_p->front = NULL;\n\t\t\t\t\tthpool_p->jobqueue_p->rear  = NULL;\n\t\t\t\t\tthpool_p->jobqueue_p->len = 0;\n\t\t\t\t\tbreak;\n\n\t\tdefault: /* if >1 jobs in queue */\n\t\t\t\t\tthpool_p->jobqueue_p->front = job_p->prev;\n\t\t\t\t\tthpool_p->jobqueue_p->len--;\n\t\t\t\t\t/* more than one job in queue -> post it */\n\t\t\t\t\tbsem_post(thpool_p->jobqueue_p->has_jobs);\n\n\t}\n\n\treturn job_p;\n}\n\n\n/* Free all queue resources back to the system */\nstatic void jobqueue_destroy(thpool_* thpool_p){\n\tjobqueue_clear(thpool_p);\n\tfree(thpool_p->jobqueue_p->has_jobs);\n}\n\n\n\n\n\n/* ======================== SYNCHRONISATION ========================= */\n\n\n/* Init semaphore to 1 or 0 */\nstatic void bsem_init(bsem *bsem_p, int value) {\n\tif (value < 0 || value > 1) {\n\t\tfprintf(stderr, \"bsem_init(): Binary semaphore can take only values 1 or 0\");\n\t\texit(1);\n\t}\n\tpthread_mutex_init(&(bsem_p->mutex), NULL);\n\tpthread_cond_init(&(bsem_p->cond), NULL);\n\tbsem_p->v = value;\n}\n\n\n/* Reset semaphore to 0 */\nstatic void bsem_reset(bsem *bsem_p) {\n\tbsem_init(bsem_p, 0);\n}\n\n\n/* Post to at least one thread */\nstatic void bsem_post(bsem *bsem_p) {\n\tpthread_mutex_lock(&bsem_p->mutex);\n\tbsem_p->v = 1;\n\tpthread_cond_signal(&bsem_p->cond);\n\tpthread_mutex_unlock(&bsem_p->mutex);\n}\n\n\n/* Post to all threads */\nstatic void bsem_post_all(bsem *bsem_p) {\n\tpthread_mutex_lock(&bsem_p->mutex);\n\tbsem_p->v = 1;\n\tpthread_cond_broadcast(&bsem_p->cond);\n\tpthread_mutex_unlock(&bsem_p->mutex);\n}\n\n\n/* Wait on semaphore until semaphore has value 0 */\nstatic void bsem_wait(bsem* bsem_p) {\n\tpthread_mutex_lock(&bsem_p->mutex);\n\twhile (bsem_p->v != 1) {\n\t\tpthread_cond_wait(&bsem_p->cond, &bsem_p->mutex);\n\t}\n\tbsem_p->v = 0;\n\tpthread_mutex_unlock(&bsem_p->mutex);\n}\n"
  },
  {
    "path": "src/tools/CMakeLists.txt",
    "content": "add_executable(lzhsenc lzhsenc.c)\nadd_executable(lzhs_scanner lzhs_scanner.c)\nadd_executable(idb_extract idb_extract.c)\nadd_executable(jffs2extract jffs2extract.c)\nadd_executable(tsfile tsfile.c)\n\ntarget_link_libraries(idb_extract mfile utils)\ntarget_link_libraries(lzhsenc lzhs)\ntarget_link_libraries(lzhs_scanner utils lzhs)\ntarget_link_libraries(jffs2extract jffs2 mfile utils)\ntarget_link_libraries(tsfile stream utils)\n"
  },
  {
    "path": "src/tools/idb_extract.c",
    "content": "/**\n * Image Database dumper\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include \"mfile.h\"\n#include \"util.h\"\n\n#define IDB_VERSION \"IDB_VERSION=\"\n#define IDB_NUM_IMG \"IDB_NUM_IMG=\"\n#define IDB_HDR_ENDMARK \"IDB_HDR_ENDMARK\"\n#define IDB_V1 \"1.1\"\n\nchar *READ_TO(MFILE *mfile, char *ptr, char ch){\n\twhile(*ptr != ch){\n\t\tptr++;\n\t\tif(moff(mfile, ptr) >= msize(mfile)){\n\t\t\tfprintf(stderr, \"Unexpected EOF!\\n\");\n\t\t\treturn NULL;\n\t\t}\n\t}\n\treturn ptr;\n}\n\nchar *READ_AFTER(MFILE *mfile, char *ptr, char ch){\n\tptr = READ_TO(mfile, ptr, ch);\n\tif(ptr == NULL)\n\t\treturn ptr;\n\treturn ++ptr;\n}\n\nstruct idb_file {\n\tuint major;\n\tuint minor;\n\tunsigned long num_img;\n};\n\nstruct __attribute__((packed)) idb_entry {\n\tuint32_t unk1;\n\tuint32_t unk2;\n\tuint32_t size;\n\tuint32_t offset;\n};\n\nint process_idb(MFILE *mf){\n\tuint8_t *data = mdata(mf, uint8_t);\n\tuint8_t *p = data;\n\n\tstruct idb_file idb;\n\n\tif(strncmp(p, IDB_VERSION, strlen(IDB_VERSION))){\n\t\tfprintf(stderr, \"Not an IDB file (no version TAG)\\n\");\n\t\treturn -1;\n\t}\n\n\tp += strlen(IDB_VERSION);\n\tif(strncmp(p, IDB_V1, strlen(IDB_V1))){\n\t\tfprintf(stderr, \"Unsupported version %.*s\\n\", READ_TO(mf, p, '\\n') - (char *)p, p);\n\t\treturn -1;\n\t}\n\n\tidb.major = 1;\n\tidb.minor = 1;\n\n\tp += strlen(IDB_V1);\n\n\tif((p=READ_AFTER(mf, p, '\\n')) == NULL)\n\t\treturn -1;\n\n\tif(strncmp(p, IDB_NUM_IMG, strlen(IDB_NUM_IMG))){\n\t\tfprintf(stderr, \"Cannot find number of pictures TAG\\n\");\n\t\treturn -1;\n\t}\n\n\tp += strlen(IDB_NUM_IMG);\n\n\tidb.num_img = strtoul((char *)p, (char **)&p, 10);\n\tif(idb.num_img == 0){\n\t\tfprintf(stderr, \"Invalid number of pictures (%zu)\\n\", idb.num_img);\n\t\treturn -1;\n\t}\n\n\tdo {\n\t\tp = READ_AFTER(mf, p, '\\n');\n\t\tif(p == NULL){\n\t\t\tfprintf(stderr, \"Cannot find header end TAG\\n\");\n\t\t\treturn -1;\n\t\t}\n\t} while(strncmp(p, IDB_HDR_ENDMARK, strlen(IDB_HDR_ENDMARK)));\n\n\tp = READ_AFTER(mf, p, '\\n');\n\tif(p == NULL){\n\t\treturn -1;\n\t}\n\n\t/* Smx: this is either wrong or we're not extracting all of the pictures */\n\tprintf(\"[IDB] Extracting %lu pictures\\n\", idb.num_img);\n\n\tstruct idb_entry *entry = (struct idb_entry *)p;\n\toff_t hdr_end = entry->offset;\n\n\tchar *file_dir = my_dirname(mf->path);\n\tchar *file_base = my_basename(mf->path);\n\tchar *file_name = remove_ext(file_base);\n\n\tchar *dest_dir;\n\tasprintf(&dest_dir, \"%s/%s\", file_dir, file_name);\n\tcreateFolder(dest_dir);\n\n\tfree(file_dir); free(file_base); free(file_name);\n\n\tuint i = 0;\n\tfor(i=0; moff(mf, entry) < hdr_end; entry++){\n\t\t/* Smx: I don't know why there are many dupes with size 0 */\n\t\tif(entry->size == 0)\n\t\t\tcontinue;\n\t\ti++;\n\t\tprintf(\"[IDB:0x%08X] Picture %u (%u bytes)\\n\", entry->offset, i, entry->size);\n\n\t\tchar *out_file;\n\t\tasprintf(&out_file, \"%s/%d.png\", dest_dir, i);\n\n\t\tMFILE *out = mfopen(out_file, \"w+\");\n\t\tif(!out){\n\t\t\tfprintf(stderr, \"Cannot open '%s' for writing\\n\", out_file);\n\t\t\tfree(out_file);\n\t\t\treturn -1;\n\t\t}\n\t\tmfile_map(out, entry->size);\n\t\tmemcpy(\n\t\t\tmdata(out, void),\n\t\t\t&data[entry->offset],\n\t\t\tentry->size\n\t\t);\n\t\tmclose(out);\n\t\tfree(out_file);\n\t}\n\n\tfree(dest_dir);\n\treturn 0;\n}\n\nint main(int argc, char *argv[]){\n\tint ret = EXIT_FAILURE;\n\tif(argc < 2){\n\t\tfprintf(stderr, \"Usage: %s [IDB_<revision>_<region>.lr]\\n\", argv[0]);\n\t\tgoto exit_e0;\n\t}\n\n\tMFILE *mf = mopen(argv[1], O_RDONLY);\n\tif(!mf){\n\t\tfprintf(stderr, \"mopen failed!\\n\");\n\t\treturn -1;\n\t}\n\n\tif(!process_idb(mf))\n\t\tret = EXIT_SUCCESS;\n\n\tmclose(mf);\n\n\texit_e0:\n\t\treturn ret;\n}\n"
  },
  {
    "path": "src/tools/jffs2extract.c",
    "content": "/**\n * Copyright 2018 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <unistd.h>\n#include <limits.h>\n\n#include \"jffs2/jffs2.h\"\n#include \"util.h\"\n\nint main(int argc, char *argv[]){\n\tif(argc < 2){\n\t\tusage:\n\t\tfprintf(stderr,\n\t\t\t\"Usage: %s [file.jffs2]\\n\"\n\t\t\t\"    -e [erase block size]\\n\"\n\t\t\t\"       if a value is specified, it will be used as erase block size\\n\"\n\t\t\t\"       if no value is specified, it will be guessed (EXPERIMENTAL)\\n\"\n\t\t\t\"    -v\\n\"\n\t\t\t\"       be verbose\\n\"\n\t\t\t\"    -k\\n\"\n\t\t\t\"       keep a copy of detected unlinked files\\n\",\n\t\targv[0]);\n\t\treturn 1;\n\t}\n\n\tint erase_size = -1;\n\tint verbose = 0;\n\tbool keep_unlinked = false;\n\n\tint c;\n\twhile ((c = getopt (argc, argv, \"e:vk\")) != -1){\n\t\tswitch(c){\n\t\t\tcase 'e':\n\t\t\t\terase_size = strtoul(optarg, NULL, 16);\n\t\t\t\tbreak;\n\t\t\tcase 'v':\n\t\t\t\tverbose++;\n\t\t\t\tbreak;\n\t\t\tcase 'k':\n\t\t\t\tkeep_unlinked = true;\n\t\t\t\tbreak;\n\t\t\tcase '?':\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tchar *filename;\n\tif(optind < argc){\n\t\tfilename = argv[optind];\n\t} else {\n\t\tgoto usage;\n\t}\n\n\tchar *dir_name = my_dirname(filename);\n\tchar *base_name = my_basename(filename);\n\n\tchar *outpath;\n\tasprintf(&outpath, \"%s/%s.unjffs2\", dir_name, base_name);\n\n\tfree(dir_name); free(base_name);\n\n\tstruct jffs2_main_args args = {\n\t\t.erase_size = erase_size,\n\t\t.keep_unlinked = keep_unlinked,\n\t\t.verbose = verbose\n\t};\n\n\tprintf(\"Extracting %s to %s\\n\", filename, outpath);\n\tint ret = jffs2extract(filename, outpath, args);\n\n\tfree(outpath);\n\treturn ret;\n}\n"
  },
  {
    "path": "src/tools/lzhs_scanner.c",
    "content": "/**\n * LZHS Scanner tool\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"mfile.h\"\n#include \"lzhs/lzhs.h\"\n#include \"mediatek.h\"\n#include \"util.h\"\n\nvoid scan_lzhs(const char *filename, int extract) {\n\tstruct lzhs_header *header = NULL;\n\tchar *outname, *outdecode;\n\n\tMFILE *file = mopen(filename, O_RDONLY);\n\tif (file == NULL) {\n\t\tprintf(\"Can't open file %s\\n\", filename);\n\t\texit(1);\n\t}\n\n\tint i, count = 0;\n\tfor (i = 0; i<msize(file); i += sizeof(*header)) {\n\t\theader = (struct lzhs_header *)(mdata(file, uint8_t) + i);\n\t\tif (_is_lzhs_mem(header)) {\n\n\t\t\tif(moff(file, header) + header->compressedSize >= msize(file)){\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcount++;\n\t\t\toff_t fileOff = moff(file, header);\n\t\t\tchar *fstring;\n\t\t\tif(!(fileOff % MTK_LOADER_OFF)){\n\t\t\t\tfstring=\"mtk loader\";\n\t\t\t} else if(!(fileOff % MTK_UBOOT_OFF)){\n\t\t\t\tfstring=\"mtk uboot\";\n\t\t\t} else {\n\t\t\t\tfstring=\"LZHS header\";\n\t\t\t}\n\n\t\t\tprintf(\"Found possible %-12s at offset @0x%08X (Checksum: 0x%02X, compressedSize: 0x%08X, uncompressedSize: 0x%08X)\\n\",\n\t\t\t\tfstring, fileOff, header->checksum, header->compressedSize, header->uncompressedSize\n\t\t\t);\n\n\t\t\tif (extract) {\n\t\t\t\tchar *dirn = my_dirname(filename);\n\t\t\t\tchar *filen = my_basename(filename);\n\t\t\t\tasprintf(&outname, \"%s/%s_file%d.lzhs\", dirn, filen, count);\n\n\t\t\t\tprintf(\"Extracting to %s\\n\", outname);\n\n\t\t\t\tMFILE *out = mfopen(outname, \"w+\");\n\t\t\t\tif (out == NULL) {\n\t\t\t\t\terr_exit(\"Cannot open file %s for writing\\n\", outname);\n\t\t\t\t}\n\n\t\t\t\tmfile_map(out, sizeof(*header) + header->compressedSize);\n\n\t\t\t\tmemcpy(\n\t\t\t\t\tmdata(out, void),\n\t\t\t\t\t(uint8_t *)header,\n\t\t\t\t\tsizeof(*header) + header->compressedSize\n\t\t\t\t);\n\n\t\t\t\tuint8_t out_checksum;\n\t\t\t\tasprintf(&outdecode, \"%s/%s_file%d.unlzhs\", dirn, filen, count);\n\t\t\t\tlzhs_decode(out, 0, outdecode, &out_checksum);\n\t\t\t\tif(extract == 2 && out_checksum != header->checksum){\n\t\t\t\t\tprintf(\"Checksum Mismatch, Skipping\\n\");\n\t\t\t\t\tunlink(outname);\n\t\t\t\t\tunlink(outdecode);\n\t\t\t\t}\n\t\t\t\tprintf(\"\\n\");\n\n\t\t\t\tmclose(out);\n\t\t\t\tfree(outname); free(outdecode);\n\t\t\t\tfree(dirn); free(filen);\n\t\t\t}\n\t\t}\n\t}\n\tmclose(file);\n}\n\nint main(int argc, char *argv[]) {\n\tif (argc < 3) {\n\t\tprintf(\"Usage: \\n\");\n\t\tprintf(\"'%s [in] 0' scan\\n\", argv[0]);\n\t\tprintf(\"'%s [in] 1' scan and extract\\n\", argv[0]);\n\t\tprintf(\"'%s [in] 2' scan and extract chunks with valid checksum only\\n\", argv[0]);\n\t\treturn 1;\n\t}\n\tscan_lzhs(argv[1], atoi(argv[2]));\n\treturn 0;\n}\n"
  },
  {
    "path": "src/tools/lzhsenc.c",
    "content": "/**\n * LZHS Encoding tool\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <stdio.h>\n#include \"lzhs/lzhs.h\"\n\nint main(int argc, char *argv[]) {\n\tif (argc < 3) {\n\t\tprintf(\"Usage: %s [in] [out.lzhs]\\n\", argv[0]);\n\t\treturn 1;\n\t}\n\tprintf(\"LZHS Encoding %s => %s...\\n\", argv[1], argv[2]);\n\tlzhs_encode(argv[1], argv[2]);\n\treturn 0;\n}\n"
  },
  {
    "path": "src/tools/tsfile.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include \"stream/tsfile.h\"\t\t/* STR and PIF */\n#include \"util.h\"\n\nint main(int argc, char *argv[]){\n\tchar *tsfile = NULL;\n\tint ac = -1, vc = -1;\n\n\tint argi; // positional argument index\n\tfor(int i=1; i<argc; i++){\n\t\tchar *arg = argv[i];\n\t\tif(*arg != '-'){\n\t\t\tswitch(argi++){\n\t\t\t\tcase 0: tsfile = arg; break;\n\t\t\t}\n\t\t} else {\n\t\t\tif(!strcmp(arg, \"-ac\")){\n\t\t\t\tif(i + 1 < argc) ac = strtoul(argv[++i], NULL, 16);\n\t\t\t} else if(!strcmp(arg, \"-vc\")){\n\t\t\t\tif(i + 1 < argc) vc = strtoul(argv[++i], NULL, 16);\n\t\t\t}\n\t\t}\n\t}\n\n\tif(tsfile == NULL){\n\t\tfprintf(stderr,\n\t\t\t\"Usage: %s [-ac type] [-vc type] <input file>\\n\"\n\t\t\t\" -ac : specify audio codec (hex)\\n\"\n\t\t\t\" -vc : specify video codec (hex)\\n\"\n\t\t, argv[0]);\n\t\treturn 1;\n\t}\n\n\t// disable output buffering\n\tsetvbuf(stdout, NULL, _IONBF, 0);\n\tsetvbuf(stderr, NULL, _IONBF, 0);\n\n\tif(!isSTRfile(tsfile)){\n\t\tfprintf(stderr, \"%s is not a valid STR file\\n\", tsfile);\n\t\treturn 1;\n\t}\n\n\tstruct tsfile_options opts = {\n\t\t.video_stream_type = vc,\n\t\t.audio_stream_type = ac,\n\t\t.append = 0\n\t};\n\n\tconvertSTR2TS(tsfile, &opts);\n\treturn 0;\n}\n"
  },
  {
    "path": "src/util.c",
    "content": "/**\n * Miscellaneous utilities\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * Copyright 2016 lprot\n * All right reserved\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdarg.h>\n#include <string.h>\n#include <ctype.h>\n#include <ftw.h>\n#include <unistd.h>\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <termios.h>\n#include <config.h>\n#include <openssl/aes.h>\n#include <inttypes.h>\n#include <libgen.h>\n#include <errno.h>\n\n#include \"common.h\"\n#include \"mfile.h\"\n#include \"util.h\"\n\n//partinfo\n#include <time.h>\n#include \"partinfo.h\"\nconst char *modelname = NULL;\npart_struct_type part_type = STRUCT_INVALID;\n\n//jffs2\n#include \"jffs2/jffs2.h\"\n\n//lzhs\n#include \"lzhs/lzhs.h\"\n\n//kernel\n#include \"u-boot/image.h\"\n#include <arpa/inet.h>\n\n//minigzip\n#include \"minigzip.h\"\n\n//boot and tzfw\n#include <elf.h>\n\n//mtk pkg\n#include \"mediatek_pkg.h\"\n\nchar *remove_ext(const char *mystr) {\n\tchar *retstr, *lastdot;\n\tif (mystr == NULL)\n\t\treturn NULL;\n\tif ((retstr = (char *)malloc(strlen(mystr) + 1)) == NULL)\n\t\treturn NULL;\n\tstrcpy(retstr, mystr);\n\tlastdot = strrchr(retstr, '.');\n\tif (lastdot != NULL)\n\t\t*lastdot = '\\0';\n\treturn retstr;\n}\n\nchar *get_ext(const char *mystr) {\n\tchar *retstr, *lastdot;\n\tif (mystr == NULL)\n\t\treturn NULL;\n\tif ((retstr = (char *)malloc(strlen(mystr) + 1)) == NULL)\n\t\treturn NULL;\n\tlastdot = strrchr(mystr, '.');\n\tif (lastdot != NULL) {\n\t\tsprintf(retstr, \"%s\", lastdot + 1);\n\t\tint i;\n\t\tfor (i = 0; retstr[i]; i++)\n\t\t\tretstr[i] = tolower(retstr[i]);\n\t}\n\treturn retstr;\n}\n\n/**\n * basename and dirname might modify the source path.\n * they also return a pointer to static memory that might be overwritten in subsequent calls\n */\nchar *my_basename(const char *path){\n\tchar *cpy = strdup(path);\n\tchar *ret = basename(cpy);\n\tret = strdup(ret);\n\tfree(cpy);\n\treturn ret;\n}\n\nchar *my_dirname(const char *path){\n\tchar *cpy = strdup(path);\n\tchar *ret = dirname(cpy);\n\tret = strdup(ret);\n\tfree(cpy);\n\treturn ret;\n}\n\nint count_tokens(const char *str, char tok, int sz){\n\tint no = 0;\n\tfor(int i=0; i<sz; i++){\n\t\tif(str[i] == tok)\n\t\t\tno++;\n\t}\n\treturn no;\n}\n\nFORMAT_PRINTF(5, 6)\nvoid print(int verbose, int newline, const char *fn, int lineno, const char *fmt, ...) {\n#if 0\n#ifndef DEBUG\n\tif (verbose > G_VERBOSE)\n\t\treturn;\n#endif\n#endif\n\n\tchar *file = my_basename(fn);\n\tchar *dir = my_dirname(fn);\n\tchar *parent = my_dirname(dir);\n\n\tconst char *relative = dir + strlen(parent) + 1;\n\n\tprintf(\"[%s/%s:%d] \", relative, file, lineno);\n\n\tfree(file);\n\tfree(dir);\n\tfree(parent);\n\n\tva_list arglist;\n\tva_start(arglist, fmt);\n\tvprintf(fmt, arglist);\n\tva_end(arglist);\n\n\tif (newline)\n\t\tprintf(\"\\n\");\n\n}\n\nvoid SwapBytes(void *pv, size_t n) {\n\tunsigned char *p = pv;\n\tfor (size_t lo = 0, hi = n - 1; hi > lo; lo++, hi--) {\n\t\tunsigned char tmp = p[lo];\n\t\tp[lo] = p[hi];\n\t\tp[hi] = tmp;\n\t}\n}\n\nvoid getch(void) {\n\tstruct termios oldattr, newattr;\n\ttcgetattr(STDIN_FILENO, &oldattr);\n\tnewattr = oldattr;\n\tnewattr.c_lflag &= ~(ICANON | ECHO);\n\ttcsetattr(STDIN_FILENO, TCSANOW, &newattr);\n\tgetchar();\n\ttcsetattr(STDIN_FILENO, TCSANOW, &oldattr);\n}\n\nvoid hexdump(const void *pAddressIn, long lSize) {\n\tchar szBuf[100];\n\tlong lIndent = 1;\n\tlong lOutLen, lIndex, lIndex2, lOutLen2;\n\tlong lRelPos;\n\tstruct {\n\t\tconst char *pData;\n\t\tunsigned long lSize;\n\t} buf;\n\tunsigned char ucTmp;\n\tconst unsigned char *pTmp, *pAddress = pAddressIn;\n\n\tbuf.pData = (const char *) pAddress;\n\tbuf.lSize = lSize;\n\n\twhile (buf.lSize > 0) {\n\t\tpTmp = (unsigned char *)buf.pData;\n\t\tlOutLen = (int)buf.lSize;\n\t\tif (lOutLen > 16)\n\t\t\tlOutLen = 16;\n\n\t\t// create a 64-character formatted output line:\n\t\tsprintf(szBuf, \" >                                                      %08tX\", pTmp - pAddress);\n\t\tlOutLen2 = lOutLen;\n\n\t\tfor (lIndex = 1 + lIndent, lIndex2 = 53 - 15 + lIndent, lRelPos = 0; lOutLen2; lOutLen2--, lIndex += 2, lIndex2++) {\n\t\t\tucTmp = *pTmp++;\n\t\t\tsprintf(szBuf + lIndex, \"%02hhX \", ucTmp);\n\t\t\tif (!isprint(ucTmp))\n\t\t\t\tucTmp = '.';\t// nonprintable char\n\t\t\tszBuf[lIndex2] = ucTmp;\n\n\t\t\tif (!(++lRelPos & 3)) {\t// extra blank after 4 bytes\n\t\t\t\tlIndex++;\n\t\t\t\tszBuf[lIndex + 2] = ' ';\n\t\t\t}\n\t\t}\n\t\tif (!(lRelPos & 3))\n\t\t\tlIndex--;\n\t\tszBuf[lIndex] = '<';\n\t\tszBuf[lIndex + 1] = ' ';\n\t\tputs(szBuf);\n\t\tbuf.pData += lOutLen;\n\t\tbuf.lSize -= lOutLen;\n\t}\n}\n\nint unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {\n\tint rv = remove(fpath);\n\tif (rv != 0)\n\t\tperror(fpath);\n\treturn rv;\n}\n\nvoid rmrf(const char *path) {\n\tstruct stat status;\n\tif (stat(path, &status) == 0)\n\t\tnftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS);\n}\n\nFORMAT_PRINTF(1, 2)\nint err_ret(const char *format, ...) {\n\tif (format != NULL) {\n\t\tva_list args;\n\t\tva_start(args, format);\n\t\tvprintf(format, args);\n\t\tva_end(args);\n\t}\n\n#ifdef __CYGWIN__\n\tputs(\"Press any key to continue...\");\n\tgetch();\n#endif\n\n\treturn EXIT_FAILURE;\n}\n\nvoid createFolder(const char *directory) {\n\tstruct stat st;\n\tif (stat(directory, &st) != 0) {\n\t\tif (mkdir((const char *)directory, 0744) != 0){\n\t\t\terr_exit(\"FATAL: Can't create directory '%s' (%s)\\n\\n\", directory, strerror(errno));\n\t\t}\n\t}\n}\n\nMFILE *is_lz4(const char *lz4file) {\n\tMFILE *file = mopen(lz4file, O_RDONLY);\n\tif (!file){\n\t\terr_exit(\"Can't open file %s\\n\\n\", lz4file);\n\t}\n\tif(!memcmp(mdata(file, uint8_t), \"LZ4P\", 4))\n\t\treturn file;\n\n\tmclose(file);\n\treturn NULL;\n}\n\nbool is_nfsb_mem(MFILE *file, off_t offset){\n\tuint8_t *data = &(mdata(file, uint8_t))[offset];\n\n\tif(memcmp(data, \"NFSB\", 4) != 0){\n\t\treturn false;\n\t}\n\n\tconst char algo_md5[] = \"md5\";\n\tconst char algo_sha256[] = \"sha256\";\n\n\tconst int offsets[] = { 0x0E, 0x1A };\n\tconst char *algos[] = { algo_md5, algo_sha256 };\n\tconst int lengths[] = { sizeof(algo_md5) - 1, sizeof(algo_sha256) - 1 };\n\n\tconst int num_offsets = countof(offsets);\n\tconst int num_algos = countof(algos);\n\n\tfor(int i=0; i<num_algos; i++){\n\t\tfor(int j=0; j<num_offsets; j++){\n\t\t\tif(memcmp(data + offsets[j], algos[i], lengths[i]) == 0){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\nMFILE *is_nfsb(const char *filename) {\n\tMFILE *file = mopen(filename, O_RDONLY);\n\tif (!file){\n\t\terr_exit(\"Can't open file %s\\n\\n\", filename);\n\t}\n\n\tif(is_nfsb_mem(file, 0))\n\t\treturn file;\n\n\tmclose(file);\n\treturn NULL;\n}\n\nvoid unnfsb(const char *filename, const char *extractedFile) {\n\tconst int headerSize = 0x1000;\n\n\tMFILE *in = mopen(filename, O_RDONLY);\n\tif(in == NULL){\n\t\terr_exit(\"Cannot open file '%s' for reading\\n\", filename);\n\t}\n\n\tMFILE *out = mfopen(extractedFile, \"w+\");\n\tif(out == NULL){\n\t\tmclose(in);\n\t\terr_exit(\"Cannot open file '%s' for writing\\n\", extractedFile);\n\t}\n\n\tlong outputSize = msize(in) - headerSize;\n\tmfile_map(out, outputSize);\n\n\tmemcpy(\n\t\tmdata(out, void),\n\t\tmdata(in, uint8_t) + headerSize,\n\t\toutputSize\n\t);\n\n\tmclose(out);\n\tmclose(in);\n}\n\nMFILE *is_gzip(const char *filename) {\n\tMFILE *file = mopen(filename, O_RDONLY);\n\tif (file == NULL) {\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\t\treturn NULL;\n\t}\n\n\tif(msize(file) < 16){\n\t\tmclose(file);\n\t\treturn NULL;\n\t}\n\n\tif(memcmp(mdata(file, uint8_t *), \"\\x1F\\x8B\\x08\", 3) != 0){\n\t\tmclose(file);\n\t\treturn NULL;\n\t}\n\n\tchar *gzfilename = mdata(file, char) + 10;\n\n\tint i;\n\tfor(i=0; gzfilename[i] != 0x00 && isprint(gzfilename[i]); i++);\n\n\tif(i > 0 && gzfilename[i] == 0x00){\n\t\treturn file;\n\t}\n\n\tmclose(file);\n\treturn NULL;\n}\n\nint is_jffs2(const char *filename) {\n\tFILE *file = fopen(filename, \"rb\");\n\tif (file == NULL) {\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\t}\n\tsize_t headerSize = 0x2;\n\tunsigned short magic = JFFS2_MAGIC_BITMASK;\n\tunsigned char buffer[headerSize];\n\tint read = fread(&buffer, 1, headerSize, file);\n\tint result = 0;\n\tif (read == headerSize) {\n\t\tresult = !memcmp(&buffer[0x0], &magic, 2);\n\t\tif (!result) {\n\t\t\tmagic = JFFS2_OLD_MAGIC_BITMASK;\n\t\t\tresult = !memcmp(&buffer[0x0], &magic, 2);\n\t\t}\n\t}\n\tfclose(file);\n\treturn result;\n}\n\nint isSTRfile(const char *filename) {\n\tFILE *file = fopen(filename, \"rb\");\n\tif (file == NULL) {\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\t}\n\tsize_t headerSize = 0xC0 * 4;\n\tunsigned char buffer[headerSize];\n\tint read = fread(&buffer, 1, headerSize, file);\n\tint result = 0;\n\tif (read == headerSize && buffer[4] == 0x47 && buffer[0xC0 + 4] == 0x47 && buffer[0xC0 * 2 + 4] == 0x47 && buffer[0xC0 * 3 + 4] == 0x47)\n\t\tresult = 1;\n\tfclose(file);\n\treturn result;\n}\n\nint isdatetime(const char *datetime) {\n\tstruct tm time_val;\n\n\t// datetime format is YYYYMMDD\n\tif (strptime(datetime, \"%Y%m%d\", &time_val) != 0\n\t\t&& ((time_val.tm_year+1900) > 2005)) {\n\t\treturn 1;\n\t} else {\n\t\treturn 0;\n\t}\n}\n\n/* detect_model - detect model and corresponding part struct */\nstatic void detect_model(const struct p2_device_info *pid) {\n\tpart_type = STRUCT_INVALID;\n\n\tint ismtk1 = !strcmp(\"mtk3569-emmc\", pid->name);  //match mtk2012\n\tint ismtk2 = !strcmp(\"mtk3598-emmc\", pid->name);  //match mtk2013\n\tint is1152 = !strcmp(\"l9_emmc\", pid->name);       //match 1152\n\tint is1154 = !strcmp(\"h13_emmc\", pid->name);      //match 1154/lg1311\n\tint isbcm1 = !strcmp(\"bcm35xx_map0\", pid->name);  //match broadcom\n\tint isbcm2 = !strcmp(\"bcm35230_map0\", pid->name); //match broadcom\n\tint ismstar = !strcmp(\"mstar_map0\", pid->name);   //match mstar\n\tint islm14 = !strcmp(\"mstar-emmc\", pid->name);    //match lm14\n\n\tif (ismtk1)\n\t\tmodelname = \"Mtk 2012 - MTK5369 (Cortex-A9 single-core)\";\n\telse if (ismtk2)\n\t\tmodelname = \"Mtk 2013 - MTK5398 (Cobra Cortex-A9 dual-core)\";\n\telse if (is1152)\n\t\tmodelname = \"LG1152 (L9)\";\n\telse if (is1154)\n\t\tmodelname = \"LG1154 (H13) / LG1311 (M14)\";\n\telse if (isbcm1)\n\t\tmodelname = \"BCM 2010 - BCM35XX\";\n\telse if (isbcm2)\n\t\tmodelname = \"BCM 2011 - BCM35230\";\n\telse if (ismstar)\n\t\tmodelname = \"Mstar Saturn6 / Saturn7 / M1 / M1a / LM1\";\n\telse if (islm14)\n\t\tmodelname = \"Mstar LM14\";\n\telse\n\t\treturn;\n\n\tif (ismtk2 || is1154 || islm14) {\n\t\tpart_type = STRUCT_PARTINFOv2;\n\t} else if (ismtk1 || is1152) {\n\t\tpart_type = STRUCT_PARTINFOv1;\n\t} else {\n\t\tpart_type = STRUCT_MTDINFO;\n\t}\n\n\treturn;\n}\n\nint isPartPakfile(const char *filename) {\n\tFILE *file = fopen(filename, \"rb\");\n\tif (file == NULL)\n\t\terr_exit(\"Can't open file %s\\n\", filename);\n\n\tstruct p2_partmap_info partinfo;\n\n\tfread(&partinfo, 1, sizeof(struct p2_partmap_info), file);\n\n\tchar *cmagic = NULL;\n\tasprintf(&cmagic, \"%x\", partinfo.magic);\n\n\tint r = isdatetime(cmagic);\n\tfree(cmagic);\n\n\tif (r == 0) {\n\t\treturn 0;\n\t}\n\n\tprintf(\"Found valid partpak magic 0x%x in %s\\n\", partinfo.magic, filename);\n\n\tdetect_model(&(partinfo.dev));\n\tfclose(file);\n\n\tif (part_type == STRUCT_INVALID) {\n\t\treturn 0;\n\t}\n\n\treturn 1;\n}\n\nint is_kernel(const char *image_file) {\n\tFILE *file = fopen(image_file, \"rb\");\n\tif (file == NULL)\n\t\terr_exit(\"Can't open file %s\", image_file);\n\n\tsize_t header_size = sizeof(struct image_header);\n\tunsigned char buffer[header_size];\n\tint read = fread(&buffer, 1, header_size, file);\n\tif (read != header_size)\n\t\treturn 0;\n\tfclose(file);\n\tstruct image_header *image_header = (struct image_header *)(&buffer);\n\tint result = image_header->ih_magic == ntohl(IH_MAGIC);\n\treturn result;\n}\n\nvoid extract_kernel(const char *image_file, const char *destination_file) {\n\tFILE *file = fopen(image_file, \"rb\");\n\tif (file == NULL)\n\t\terr_exit(\"Can't open file %s\", image_file);\n\n\tfseek(file, 0, SEEK_END);\n\tint fileLength = ftell(file);\n\trewind(file);\n\tunsigned char *buffer = malloc(fileLength);\n\tint read = fread(buffer, 1, fileLength, file);\n\tif (read != fileLength) {\n\t\terr_exit(\"Error reading file. read %d bytes from %d.\\n\", read, fileLength);\n\t\tfree(buffer);\n\t}\n\tfclose(file);\n\n\tFILE *out = fopen(destination_file, \"wb\");\n\tint header_size = sizeof(struct image_header);\n\tfwrite(buffer + header_size, 1, read - header_size, out);\n\tfree(buffer);\n\tfclose(out);\n}\n\n/**\n * asprintf that allows reuse of strp in variadic arguments (frees strp and replaces it with newly allocated string)\n */\nFORMAT_PRINTF(2, 3)\nint asprintf_inplace(char **strp, const char *fmt, ...) {\n    if ((strp == NULL) || (fmt == NULL)) {\n        err_exit(\"Error: %s called with NULL argument.\\n\", __func__);\n    }\n\n\tva_list args;\n    va_start(args, fmt);\n\tchar *new_strp = NULL;\n    int result = vasprintf(&new_strp, fmt, args);\n    va_end(args);\n\n    free(*strp);\n    *strp = new_strp;\n\n    return result;\n}\n"
  },
  {
    "path": "src/util_crypto.c",
    "content": "/**\n * Miscellaneous utilities\n * Copyright 2016 Smx <smxdev4@gmail.com>\n * All right reserved\n */\n#include <string.h>\n#include <stdint.h>\n#include <ctype.h>\n#include <openssl/evp.h>\n#include <openssl/err.h>\n#include <openssl/aes.h>\n#include \"config.h\"\n#include \"util.h\"\n#include \"util_crypto.h\"\n\nstatic char *keyFileName = NULL;\n\nvoid setKeyFile(const char *keyFile){\n\tif(keyFileName != NULL)\n\t\tfree(keyFileName);\n\tkeyFileName = (char *)keyFile;\n}\n\nvoid setKeyFile_LG(){\n\tchar *path;\n\tasprintf(&path, \"%s/AES.key\", config_opts.config_dir);\n\tsetKeyFile(path);\n}\n\nvoid setKeyFile_MTK(){\n\tchar *path;\n\tasprintf(&path, \"%s/MTK.key\", config_opts.config_dir);\n\tsetKeyFile(path);\n}\n\nKeyPair *find_AES_key(uint8_t *in_data, size_t in_data_size, CompareFunc fCompare, int key_type, void **dataOut, int verbose){\n\tAES_KEY aesKey;\n\tint found = 0;\n\n\tif(keyFileName == NULL){\n\t\terr_exit(\"No key file selected!\\n\");\n\t}\n\n\tFILE *fp = fopen(keyFileName, \"r\");\n\tif (fp == NULL) {\n\t\tfprintf(stderr, \"Error: Cannot open key file.\\n\");\n\t\treturn NULL;\n\t}\n\n\tuint8_t key_buf[MAX_KEY_SIZE];\n\tuint8_t iv_buf[MAX_KEY_SIZE];\n\tmemset(&key_buf, 0x00, sizeof(key_buf));\n\tmemset(&iv_buf, 0x00, sizeof(iv_buf));\n\n\tssize_t read;\n\tsize_t len = 0;\n\tchar *line = NULL;\n\n\twhile ((read = getline(&line, &len, fp)) != -1) {\n\t\tif ((line[0] == '#') || (line[0] == '\\0') ||\n\t\t    (line[0] == '\\n') || (line[0] == '\\r')) {\n\t\t\t/* skip commented or empty line */\n\t\t\tcontinue;\n\t\t}\n\n\t\tchar *pos = line;\n\t\tuint8_t *buf = (uint8_t *)&key_buf;\n\n\t\tsize_t count;\n\t\tif(verbose){\n\t\t\tprintf(\"[+] Trying AES Key \");\n\t\t}\n\n\t\tread_key:\n\t\tfor (count = 0; count < MAX_KEY_SIZE; count++) {\n\t\t\tif(!isprint(*pos) || *pos == ','){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(!sscanf(pos, \"%2hhx\", &buf[count])){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(verbose){\n\t\t\t\tprintf(\"%02X\", buf[count]);\n\t\t\t}\n\t\t\tpos += 2;\n\t\t}\n\t\tif(key_type == KEY_CBC && *pos == ','){ //repeat for IV\n\t\t\tbuf = (uint8_t *)&iv_buf;\n\t\t\tpos++;\n\t\t\tif(verbose)\n\t\t\t\tprintf(\", IV: \");\n\t\t\tgoto read_key;\n\t\t}\n\n\t\tint key_bits = count * 8;\n\t\tif(verbose){\n\t\t\tprintf(\" (aes %d) %s\\n\", key_bits, pos);\n\t\t}\n\t\tAES_set_decrypt_key((uint8_t *)&key_buf, key_bits, &aesKey);\n\n\t\tuint8_t *tmp_data = calloc(1, in_data_size);\n\n\t\tswitch(key_type){\n\t\t\tcase KEY_CBC:;\n\t\t\t\tuint8_t iv_tmp[16];\n\t\t\t\tmemcpy(&iv_tmp, &iv_buf, sizeof(iv_tmp));\n\t\t\t\tAES_cbc_encrypt(in_data, tmp_data, in_data_size, &aesKey, (uint8_t *)&iv_tmp, AES_DECRYPT);\n\t\t\t\tbreak;\n\t\t\tcase KEY_ECB:;\n\t\t\t\tsize_t blocks = in_data_size / AES_BLOCK_SIZE;\n\t\t\t\tsize_t i;\n\t\t\t\tfor(i=0; i<blocks; i++)\n\t\t\t\t\tAES_ecb_encrypt(&in_data[AES_BLOCK_SIZE * i], &tmp_data[AES_BLOCK_SIZE * i], &aesKey, AES_DECRYPT);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\terr_exit(\"Unsupported key type %d\\n\", key_type);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tfound = fCompare(tmp_data, in_data_size) > 0;\n\n\t\tif(found && dataOut != NULL){\n\t\t\t*dataOut = tmp_data;\n\t\t} else {\n\t\t\tfree(tmp_data);\n\t\t}\n\n\t\tif(found){\n\t\t\tKeyPair *key = calloc(1, sizeof(KeyPair));\n\t\t\tmemcpy(&(key->key), &aesKey, sizeof(aesKey));\n\t\t\tif(key_type == KEY_CBC){\n\t\t\t\tmemcpy(&(key->ivec), &iv_buf, sizeof(iv_buf));\n\t\t\t}\n\t\t\tfree(line);\n\t\t\tfclose(fp);\n\t\t\treturn key;\n\t\t}\n\t}\n\n\tif(line != NULL){\n\t\tfree(line);\n\t}\n\n\tfclose(fp);\n\n\treturn NULL;\n}\n"
  }
]