From 87d35f0d16d3be56020f9e6295cc8bfa0c657d27 Mon Sep 17 00:00:00 2001 From: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Date: Sat, 15 Oct 2022 20:15:46 +0200 Subject: [PATCH] fix: remove some unused libs Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> --- CMakeLists.txt | 2 - launcher/CMakeLists.txt | 1 - libraries/README.md | 16 +- libraries/classparser/CMakeLists.txt | 42 - libraries/classparser/include/classparser.h | 27 - .../classparser/include/classparser_config.h | 22 - libraries/classparser/src/annotations.cpp | 85 -- libraries/classparser/src/annotations.h | 278 ---- libraries/classparser/src/classfile.h | 156 --- libraries/classparser/src/classparser.cpp | 83 -- libraries/classparser/src/constants.h | 232 ---- libraries/classparser/src/errors.h | 8 - libraries/classparser/src/javaendian.h | 59 - libraries/classparser/src/membuffer.h | 63 - libraries/xz-embedded/CMakeLists.txt | 26 - libraries/xz-embedded/include/xz.h | 321 ----- libraries/xz-embedded/src/xz_config.h | 119 -- libraries/xz-embedded/src/xz_crc32.c | 61 - libraries/xz-embedded/src/xz_crc64.c | 52 - libraries/xz-embedded/src/xz_dec_bcj.c | 588 -------- libraries/xz-embedded/src/xz_dec_lzma2.c | 1231 ----------------- libraries/xz-embedded/src/xz_dec_stream.c | 860 ------------ libraries/xz-embedded/src/xz_lzma2.h | 204 --- libraries/xz-embedded/src/xz_private.h | 150 -- libraries/xz-embedded/src/xz_stream.h | 62 - libraries/xz-embedded/xzminidec.c | 144 -- 26 files changed, 1 insertion(+), 4891 deletions(-) delete mode 100644 libraries/classparser/CMakeLists.txt delete mode 100644 libraries/classparser/include/classparser.h delete mode 100644 libraries/classparser/include/classparser_config.h delete mode 100644 libraries/classparser/src/annotations.cpp delete mode 100644 libraries/classparser/src/annotations.h delete mode 100644 libraries/classparser/src/classfile.h delete mode 100644 libraries/classparser/src/classparser.cpp delete mode 100644 libraries/classparser/src/constants.h delete mode 100644 libraries/classparser/src/errors.h delete mode 100644 libraries/classparser/src/javaendian.h delete mode 100644 libraries/classparser/src/membuffer.h delete mode 100644 libraries/xz-embedded/CMakeLists.txt delete mode 100644 libraries/xz-embedded/include/xz.h delete mode 100644 libraries/xz-embedded/src/xz_config.h delete mode 100644 libraries/xz-embedded/src/xz_crc32.c delete mode 100644 libraries/xz-embedded/src/xz_crc64.c delete mode 100644 libraries/xz-embedded/src/xz_dec_bcj.c delete mode 100644 libraries/xz-embedded/src/xz_dec_lzma2.c delete mode 100644 libraries/xz-embedded/src/xz_dec_stream.c delete mode 100644 libraries/xz-embedded/src/xz_lzma2.h delete mode 100644 libraries/xz-embedded/src/xz_private.h delete mode 100644 libraries/xz-embedded/src/xz_stream.h delete mode 100644 libraries/xz-embedded/xzminidec.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 310cec59..caecddbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -305,7 +305,6 @@ add_subdirectory(libraries/systeminfo) # system information library add_subdirectory(libraries/hoedown) # markdown parser add_subdirectory(libraries/launcher) # java based launcher part for Minecraft add_subdirectory(libraries/javacheck) # java compatibility checker -add_subdirectory(libraries/xz-embedded) # xz compression if (FORCE_BUNDLED_QUAZIP) message(STATUS "Using bundled QuaZip") set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts. @@ -316,7 +315,6 @@ else() endif() add_subdirectory(libraries/rainbow) # Qt extension for colors add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions -add_subdirectory(libraries/classparser) # class parser library if(NOT tomlplusplus_FOUND) message(STATUS "Using bundled tomlplusplus") add_subdirectory(libraries/tomlplusplus) # toml parser diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index c7d0d68c..6ad91a85 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -968,7 +968,6 @@ add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHE target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(Launcher_logic systeminfo - Launcher_classparser Launcher_murmur2 nbt++ ${ZLIB_LIBRARIES} diff --git a/libraries/README.md b/libraries/README.md index dfb57a65..9a26dd69 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -2,14 +2,6 @@ This folder has third-party or otherwise external libraries needed for other parts to work. -## classparser - -A simplistic parser for Java class files. - -This library has served as a base for some (much more full-featured and advanced) work under NDA for AVG. It, however, should NOT be confused with that work. - -Copyright belongs to Petr Mrázek, unless explicitly stated otherwise in the source files. Available under the Apache 2.0 license. - ## filesystem Gulrak's implementation of C++17 std::filesystem for C++11 /C++14/C++17/C++20 on Windows, macOS, Linux and FreeBSD. @@ -191,10 +183,4 @@ A TOML language parser. Used by Forge 1.14+ to store mod metadata. See [github repo](https://github.com/marzer/tomlplusplus). -Licenced under the MIT licence. - -## xz-embedded - -Tiny implementation of LZMA2 de/compression. This format was only used by Forge to save bandwidth. - -Public domain. +Licenced under the MIT licence. \ No newline at end of file diff --git a/libraries/classparser/CMakeLists.txt b/libraries/classparser/CMakeLists.txt deleted file mode 100644 index 05412c30..00000000 --- a/libraries/classparser/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -project(classparser) - -set(CMAKE_AUTOMOC ON) - -######## Check endianness ######## -include(TestBigEndian) -test_big_endian(BIGENDIAN) -if(${BIGENDIAN}) - add_definitions(-DMULTIMC_BIG_ENDIAN) -endif(${BIGENDIAN}) - -# Find Qt -if(QT_VERSION_MAJOR EQUAL 5) - find_package(Qt5 COMPONENTS Core REQUIRED) -elseif(Launcher_QT_VERSION_MAJOR EQUAL 6) - find_package(Qt6 COMPONENTS Core REQUIRED) -endif() - -set(CLASSPARSER_HEADERS -# Public headers -include/classparser_config.h -include/classparser.h - -# Private headers -src/annotations.h -src/classfile.h -src/constants.h -src/errors.h -src/javaendian.h -src/membuffer.h -) - -set(CLASSPARSER_SOURCES -src/classparser.cpp -src/annotations.cpp -) - -add_definitions(-DCLASSPARSER_LIBRARY) - -add_library(Launcher_classparser STATIC ${CLASSPARSER_SOURCES} ${CLASSPARSER_HEADERS}) -target_include_directories(Launcher_classparser PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(Launcher_classparser QuaZip::QuaZip Qt${QT_VERSION_MAJOR}::Core) diff --git a/libraries/classparser/include/classparser.h b/libraries/classparser/include/classparser.h deleted file mode 100644 index 3660026b..00000000 --- a/libraries/classparser/include/classparser.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright 2013-2021 MultiMC Contributors - * - * Authors: Orochimarufan - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once -#include -#include "classparser_config.h" - -namespace classparser -{ -/** - * @brief Get the version from a minecraft.jar by parsing its class files. Expensive! - */ -QString GetMinecraftJarVersion(QString jar); -} diff --git a/libraries/classparser/include/classparser_config.h b/libraries/classparser/include/classparser_config.h deleted file mode 100644 index 7bfae7cc..00000000 --- a/libraries/classparser/include/classparser_config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2013-2021 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#ifdef CLASSPARSER_LIBRARY -#define CLASSPARSER_EXPORT Q_DECL_EXPORT -#else -#define CLASSPARSER_EXPORT Q_DECL_IMPORT -#endif diff --git a/libraries/classparser/src/annotations.cpp b/libraries/classparser/src/annotations.cpp deleted file mode 100644 index 89b201bc..00000000 --- a/libraries/classparser/src/annotations.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "classfile.h" -#include "annotations.h" -#include - -namespace java -{ -std::string annotation::toString() -{ - std::ostringstream ss; - ss << "Annotation type : " << type_index << " - " << pool[type_index].str_data << std::endl; - ss << "Contains " << name_val_pairs.size() << " pairs:" << std::endl; - for (unsigned i = 0; i < name_val_pairs.size(); i++) - { - std::pair &val = name_val_pairs[i]; - auto name_idx = val.first; - ss << pool[name_idx].str_data << "(" << name_idx << ")" - << " = " << val.second->toString() << std::endl; - } - return ss.str(); -} - -annotation *annotation::read(util::membuffer &input, constant_pool &pool) -{ - uint16_t type_index = 0; - input.read_be(type_index); - annotation *ann = new annotation(type_index, pool); - - uint16_t num_pairs = 0; - input.read_be(num_pairs); - while (num_pairs) - { - uint16_t name_idx = 0; - // read name index - input.read_be(name_idx); - auto elem = element_value::readElementValue(input, pool); - // read value - ann->add_pair(name_idx, elem); - num_pairs--; - } - return ann; -} - -element_value *element_value::readElementValue(util::membuffer &input, - java::constant_pool &pool) -{ - element_value_type type = INVALID; - input.read(type); - uint16_t index = 0; - uint16_t index2 = 0; - std::vector vals; - switch (type) - { - case PRIMITIVE_BYTE: - case PRIMITIVE_CHAR: - case PRIMITIVE_DOUBLE: - case PRIMITIVE_FLOAT: - case PRIMITIVE_INT: - case PRIMITIVE_LONG: - case PRIMITIVE_SHORT: - case PRIMITIVE_BOOLEAN: - case STRING: - input.read_be(index); - return new element_value_simple(type, index, pool); - case ENUM_CONSTANT: - input.read_be(index); - input.read_be(index2); - return new element_value_enum(type, index, index2, pool); - case CLASS: // Class - input.read_be(index); - return new element_value_class(type, index, pool); - case ANNOTATION: // Annotation - // FIXME: runtime visibility info needs to be passed from parent - return new element_value_annotation(ANNOTATION, annotation::read(input, pool), pool); - case ARRAY: // Array - input.read_be(index); - for (int i = 0; i < index; i++) - { - vals.push_back(element_value::readElementValue(input, pool)); - } - return new element_value_array(ARRAY, vals, pool); - default: - throw java::classfile_exception(); - } -} -} diff --git a/libraries/classparser/src/annotations.h b/libraries/classparser/src/annotations.h deleted file mode 100644 index 15bf05a4..00000000 --- a/libraries/classparser/src/annotations.h +++ /dev/null @@ -1,278 +0,0 @@ -#pragma once -#include "classfile.h" -#include -#include - -namespace java -{ -enum element_value_type : uint8_t -{ - INVALID = 0, - STRING = 's', - ENUM_CONSTANT = 'e', - CLASS = 'c', - ANNOTATION = '@', - ARRAY = '[', // one array dimension - PRIMITIVE_INT = 'I', // integer - PRIMITIVE_BYTE = 'B', // signed byte - PRIMITIVE_CHAR = 'C', // Unicode character code point in the Basic Multilingual Plane, - // encoded with UTF-16 - PRIMITIVE_DOUBLE = 'D', // double-precision floating-point value - PRIMITIVE_FLOAT = 'F', // single-precision floating-point value - PRIMITIVE_LONG = 'J', // long integer - PRIMITIVE_SHORT = 'S', // signed short - PRIMITIVE_BOOLEAN = 'Z' // true or false -}; -/** - * The element_value structure is a discriminated union representing the value of an - *element-value pair. - * It is used to represent element values in all attributes that describe annotations - * - RuntimeVisibleAnnotations - * - RuntimeInvisibleAnnotations - * - RuntimeVisibleParameterAnnotations - * - RuntimeInvisibleParameterAnnotations). - * - * The element_value structure has the following format: - */ -class element_value -{ -protected: - element_value_type type; - constant_pool &pool; - -public: - element_value(element_value_type type, constant_pool &pool) : type(type), pool(pool) {}; - virtual ~element_value() {} - - element_value_type getElementValueType() - { - return type; - } - - virtual std::string toString() = 0; - - static element_value *readElementValue(util::membuffer &input, constant_pool &pool); -}; - -/** - * Each value of the annotations table represents a single runtime-visible annotation on a - * program element. - * The annotation structure has the following format: - */ -class annotation -{ -public: - typedef std::vector> value_list; - -protected: - /** - * The value of the type_index item must be a valid index into the constant_pool table. - * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure - * representing a field descriptor representing the annotation type corresponding - * to the annotation represented by this annotation structure. - */ - uint16_t type_index; - /** - * map between element_name_index and value. - * - * The value of the element_name_index item must be a valid index into the constant_pool - *table. - * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure - *representing - * a valid field descriptor (§4.3.2) that denotes the name of the annotation type element - *represented - * by this element_value_pairs entry. - */ - value_list name_val_pairs; - /** - * Reference to the parent constant pool - */ - constant_pool &pool; - -public: - annotation(uint16_t type_index, constant_pool &pool) - : type_index(type_index), pool(pool) {}; - ~annotation() - { - for (unsigned i = 0; i < name_val_pairs.size(); i++) - { - delete name_val_pairs[i].second; - } - } - void add_pair(uint16_t key, element_value *value) - { - name_val_pairs.push_back(std::make_pair(key, value)); - } - ; - value_list::const_iterator begin() - { - return name_val_pairs.cbegin(); - } - value_list::const_iterator end() - { - return name_val_pairs.cend(); - } - std::string toString(); - static annotation *read(util::membuffer &input, constant_pool &pool); -}; -typedef std::vector annotation_table; - -/// type for simple value annotation elements -class element_value_simple : public element_value -{ -protected: - /// index of the constant in the constant pool - uint16_t index; - -public: - element_value_simple(element_value_type type, uint16_t index, constant_pool &pool) - : element_value(type, pool), index(index) { - // TODO: verify consistency - }; - uint16_t getIndex() - { - return index; - } - virtual std::string toString() - { - return pool[index].toString(); - } - ; -}; -/// The enum_const_value item is used if the tag item is 'e'. -class element_value_enum : public element_value -{ -protected: - /** - * The value of the type_name_index item must be a valid index into the constant_pool table. - * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure - * representing a valid field descriptor (§4.3.2) that denotes the internal form of the - * binary - * name (§4.2.1) of the type of the enum constant represented by this element_value - * structure. - */ - uint16_t typeIndex; - /** - * The value of the const_name_index item must be a valid index into the constant_pool - * table. - * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure - * representing the simple name of the enum constant represented by this element_value - * structure. - */ - uint16_t valueIndex; - -public: - element_value_enum(element_value_type type, uint16_t typeIndex, uint16_t valueIndex, - constant_pool &pool) - : element_value(type, pool), typeIndex(typeIndex), valueIndex(valueIndex) - { - // TODO: verify consistency - } - uint16_t getValueIndex() - { - return valueIndex; - } - uint16_t getTypeIndex() - { - return typeIndex; - } - virtual std::string toString() - { - return "enum value"; - } - ; -}; - -class element_value_class : public element_value -{ -protected: - /** - * The class_info_index item must be a valid index into the constant_pool table. - * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure - * representing the return descriptor (§4.3.3) of the type that is reified by the class - * represented by this element_value structure. - * - * For example, 'V' for Void.class, 'Ljava/lang/Object;' for Object, etc. - * - * Or in plain english, you can store type information in annotations. Yay. - */ - uint16_t classIndex; - -public: - element_value_class(element_value_type type, uint16_t classIndex, constant_pool &pool) - : element_value(type, pool), classIndex(classIndex) - { - // TODO: verify consistency - } - uint16_t getIndex() - { - return classIndex; - } - virtual std::string toString() - { - return "class"; - } - ; -}; - -/// nested annotations... yay -class element_value_annotation : public element_value -{ -private: - annotation *nestedAnnotation; - -public: - element_value_annotation(element_value_type type, annotation *nestedAnnotation, - constant_pool &pool) - : element_value(type, pool), nestedAnnotation(nestedAnnotation) {}; - ~element_value_annotation() - { - if (nestedAnnotation) - { - delete nestedAnnotation; - nestedAnnotation = nullptr; - } - } - virtual std::string toString() - { - return "nested annotation"; - } - ; -}; - -/// and arrays! -class element_value_array : public element_value -{ -public: - typedef std::vector elem_vec; - -protected: - elem_vec values; - -public: - element_value_array(element_value_type type, std::vector &values, - constant_pool &pool) - : element_value(type, pool), values(values) {}; - ~element_value_array() - { - for (unsigned i = 0; i < values.size(); i++) - { - delete values[i]; - } - } - ; - elem_vec::const_iterator begin() - { - return values.cbegin(); - } - elem_vec::const_iterator end() - { - return values.cend(); - } - virtual std::string toString() - { - return "array"; - } - ; -}; -} \ No newline at end of file diff --git a/libraries/classparser/src/classfile.h b/libraries/classparser/src/classfile.h deleted file mode 100644 index d629dde1..00000000 --- a/libraries/classparser/src/classfile.h +++ /dev/null @@ -1,156 +0,0 @@ -#pragma once -#include "membuffer.h" -#include "constants.h" -#include "annotations.h" -#include -namespace java -{ -/** - * Class representing a Java .class file - */ -class classfile : public util::membuffer -{ -public: - classfile(char *data, std::size_t size) : membuffer(data, size) - { - valid = false; - is_synthetic = false; - read_be(magic); - if (magic != 0xCAFEBABE) - throw classfile_exception(); - read_be(minor_version); - read_be(major_version); - constants.load(*this); - read_be(access_flags); - read_be(this_class); - read_be(super_class); - - // Interfaces - uint16_t iface_count = 0; - read_be(iface_count); - while (iface_count) - { - uint16_t iface; - read_be(iface); - interfaces.push_back(iface); - iface_count--; - } - - // Fields - // read fields (and attributes from inside fields) (and possible inner classes. yay for - // recursion!) - // for now though, we will ignore all attributes - /* - * field_info - * { - * u2 access_flags; - * u2 name_index; - * u2 descriptor_index; - * u2 attributes_count; - * attribute_info attributes[attributes_count]; - * } - */ - uint16_t field_count = 0; - read_be(field_count); - while (field_count) - { - // skip field stuff - skip(6); - // and skip field attributes - uint16_t attr_count = 0; - read_be(attr_count); - while (attr_count) - { - skip(2); - uint32_t attr_length = 0; - read_be(attr_length); - skip(attr_length); - attr_count--; - } - field_count--; - } - - // class methods - /* - * method_info - * { - * u2 access_flags; - * u2 name_index; - * u2 descriptor_index; - * u2 attributes_count; - * attribute_info attributes[attributes_count]; - * } - */ - uint16_t method_count = 0; - read_be(method_count); - while (method_count) - { - skip(6); - // and skip method attributes - uint16_t attr_count = 0; - read_be(attr_count); - while (attr_count) - { - skip(2); - uint32_t attr_length = 0; - read_be(attr_length); - skip(attr_length); - attr_count--; - } - method_count--; - } - - // class attributes - // there are many kinds of attributes. this is just the generic wrapper structure. - // type is decided by attribute name. extensions to the standard are *possible* - // class annotations are one kind of a attribute (one per class) - /* - * attribute_info - * { - * u2 attribute_name_index; - * u4 attribute_length; - * u1 info[attribute_length]; - * } - */ - uint16_t class_attr_count = 0; - read_be(class_attr_count); - while (class_attr_count) - { - uint16_t name_idx = 0; - read_be(name_idx); - uint32_t attr_length = 0; - read_be(attr_length); - - auto name = constants[name_idx]; - if (name.str_data == "RuntimeVisibleAnnotations") - { - uint16_t num_annotations = 0; - read_be(num_annotations); - while (num_annotations) - { - visible_class_annotations.push_back(annotation::read(*this, constants)); - num_annotations--; - } - } - else - skip(attr_length); - class_attr_count--; - } - valid = true; - } - ; - bool valid; - bool is_synthetic; - uint32_t magic; - uint16_t minor_version; - uint16_t major_version; - constant_pool constants; - uint16_t access_flags; - uint16_t this_class; - uint16_t super_class; - // interfaces this class implements ? must be. investigate. - std::vector interfaces; - // FIXME: doesn't free up memory on delete - java::annotation_table visible_class_annotations; -}; -} diff --git a/libraries/classparser/src/classparser.cpp b/libraries/classparser/src/classparser.cpp deleted file mode 100644 index 601521f6..00000000 --- a/libraries/classparser/src/classparser.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright 2013-2021 MultiMC Contributors - * - * Authors: Orochimarufan - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "classfile.h" -#include "classparser.h" - -#include -#include -#include - -namespace classparser -{ - -QString GetMinecraftJarVersion(QString jarName) -{ - QString version; - - // check if minecraft.jar exists - QFile jar(jarName); - if (!jar.exists()) - return version; - - // open minecraft.jar - QuaZip zip(&jar); - if (!zip.open(QuaZip::mdUnzip)) - return version; - - // open Minecraft.class - zip.setCurrentFile("net/minecraft/client/Minecraft.class", QuaZip::csSensitive); - QuaZipFile Minecraft(&zip); - if (!Minecraft.open(QuaZipFile::ReadOnly)) - return version; - - // read Minecraft.class - qint64 size = Minecraft.size(); - char *classfile = new char[size]; - Minecraft.read(classfile, size); - - // parse Minecraft.class - try - { - char *temp = classfile; - java::classfile MinecraftClass(temp, size); - java::constant_pool constants = MinecraftClass.constants; - for (java::constant_pool::container_type::const_iterator iter = constants.begin(); - iter != constants.end(); iter++) - { - const java::constant &constant = *iter; - if (constant.type != java::constant_type_t::j_string_data) - continue; - const std::string &str = constant.str_data; - qDebug() << QString::fromStdString(str); - if (str.compare(0, 20, "Minecraft Minecraft ") == 0) - { - version = str.substr(20).data(); - break; - } - } - } - catch (const java::classfile_exception &) { } - - // clean up - delete[] classfile; - Minecraft.close(); - zip.close(); - jar.close(); - - return version; -} -} diff --git a/libraries/classparser/src/constants.h b/libraries/classparser/src/constants.h deleted file mode 100644 index 47b325b9..00000000 --- a/libraries/classparser/src/constants.h +++ /dev/null @@ -1,232 +0,0 @@ -#pragma once -#include "errors.h" -#include "membuffer.h" -#include - -namespace java -{ -enum class constant_type_t : uint8_t -{ - j_hole = 0, // HACK: this is a hole in the array, because java is crazy - j_string_data = 1, - j_int = 3, - j_float = 4, - j_long = 5, - j_double = 6, - j_class = 7, - j_string = 8, - j_fieldref = 9, - j_methodref = 10, - j_interface_methodref = 11, - j_nameandtype = 12 - // FIXME: missing some constant types, see https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4 -}; - -struct ref_type_t -{ - /** - * Class reference: - * an index within the constant pool to a UTF-8 string containing - * the fully qualified class name (in internal format) - * Used for j_class, j_fieldref, j_methodref and j_interface_methodref - */ - uint16_t class_idx; - // used for j_fieldref, j_methodref and j_interface_methodref - uint16_t name_and_type_idx; -}; - -struct name_and_type_t -{ - uint16_t name_index; - uint16_t descriptor_index; -}; - -class constant -{ -public: - constant_type_t type = constant_type_t::j_hole; - - constant(util::membuffer &buf) - { - buf.read(type); - - // load data depending on type - switch (type) - { - case constant_type_t::j_float: - buf.read_be(data.int_data); - break; - case constant_type_t::j_int: - buf.read_be(data.int_data); // same as float data really - break; - case constant_type_t::j_double: - buf.read_be(data.long_data); - break; - case constant_type_t::j_long: - buf.read_be(data.long_data); // same as double - break; - case constant_type_t::j_class: - buf.read_be(data.ref_type.class_idx); - break; - case constant_type_t::j_fieldref: - case constant_type_t::j_methodref: - case constant_type_t::j_interface_methodref: - buf.read_be(data.ref_type.class_idx); - buf.read_be(data.ref_type.name_and_type_idx); - break; - case constant_type_t::j_string: - buf.read_be(data.index); - break; - case constant_type_t::j_string_data: - // HACK HACK: for now, we call these UTF-8 and do no further processing. - // Later, we should do some decoding. It's really modified UTF-8 - // * U+0000 is represented as 0xC0,0x80 invalid character - // * any single zero byte ends the string - // * characters above U+10000 are encoded like in CESU-8 - buf.read_jstr(str_data); - break; - case constant_type_t::j_nameandtype: - buf.read_be(data.name_and_type.name_index); - buf.read_be(data.name_and_type.descriptor_index); - break; - default: - // invalid constant type! - throw classfile_exception(); - } - } - constant(int) - { - } - - std::string toString() - { - std::ostringstream ss; - switch (type) - { - case constant_type_t::j_hole: - ss << "Fake legacy entry"; - break; - case constant_type_t::j_float: - ss << "Float: " << data.float_data; - break; - case constant_type_t::j_double: - ss << "Double: " << data.double_data; - break; - case constant_type_t::j_int: - ss << "Int: " << data.int_data; - break; - case constant_type_t::j_long: - ss << "Long: " << data.long_data; - break; - case constant_type_t::j_string_data: - ss << "StrData: " << str_data; - break; - case constant_type_t::j_string: - ss << "Str: " << data.index; - break; - case constant_type_t::j_fieldref: - ss << "FieldRef: " << data.ref_type.class_idx << " " << data.ref_type.name_and_type_idx; - break; - case constant_type_t::j_methodref: - ss << "MethodRef: " << data.ref_type.class_idx << " " << data.ref_type.name_and_type_idx; - break; - case constant_type_t::j_interface_methodref: - ss << "IfMethodRef: " << data.ref_type.class_idx << " " << data.ref_type.name_and_type_idx; - break; - case constant_type_t::j_class: - ss << "Class: " << data.ref_type.class_idx; - break; - case constant_type_t::j_nameandtype: - ss << "NameAndType: " << data.name_and_type.name_index << " " - << data.name_and_type.descriptor_index; - break; - default: - ss << "Invalid entry (" << int(type) << ")"; - break; - } - return ss.str(); - } - - std::string str_data; /** String data in 'modified utf-8'.*/ - - // store everything here. - union - { - int32_t int_data; - int64_t long_data; - float float_data; - double double_data; - uint16_t index; - ref_type_t ref_type; - name_and_type_t name_and_type; - } data = {0}; -}; - -/** - * A helper class that represents the custom container used in Java class file for storage of - * constants - */ -class constant_pool -{ -public: - /** - * Create a pool of constants - */ - constant_pool() - { - } - /** - * Load a java constant pool - */ - void load(util::membuffer &buf) - { - // FIXME: @SANITY this should check for the end of buffer. - uint16_t length = 0; - buf.read_be(length); - length--; - const constant *last_constant = nullptr; - while (length) - { - const constant &cnst = constant(buf); - constants.push_back(cnst); - last_constant = &constants[constants.size() - 1]; - if (last_constant->type == constant_type_t::j_double || - last_constant->type == constant_type_t::j_long) - { - // push in a fake constant to preserve indexing - constants.push_back(constant(0)); - length -= 2; - } - else - { - length--; - } - } - } - typedef std::vector container_type; - /** - * Access constants based on jar file index numbers (index of the first element is 1) - */ - java::constant &operator[](std::size_t constant_index) - { - if (constant_index == 0 || constant_index > constants.size()) - { - throw classfile_exception(); - } - return constants[constant_index - 1]; - } - ; - container_type::const_iterator begin() const - { - return constants.begin(); - } - ; - container_type::const_iterator end() const - { - return constants.end(); - } - -private: - container_type constants; -}; -} diff --git a/libraries/classparser/src/errors.h b/libraries/classparser/src/errors.h deleted file mode 100644 index ddbbd828..00000000 --- a/libraries/classparser/src/errors.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include -namespace java -{ -class classfile_exception : public std::exception -{ -}; -} diff --git a/libraries/classparser/src/javaendian.h b/libraries/classparser/src/javaendian.h deleted file mode 100644 index 5a6e107b..00000000 --- a/libraries/classparser/src/javaendian.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -#include - -/** - * Swap bytes between big endian and local number representation - */ -namespace util -{ -#ifdef MULTIMC_BIG_ENDIAN -inline uint64_t bigswap(uint64_t x) -{ - return x; -} - -inline uint32_t bigswap(uint32_t x) -{ - return x; -} - -inline uint16_t bigswap(uint16_t x) -{ - return x; -} - -#else -inline uint64_t bigswap(uint64_t x) -{ - return (x >> 56) | ((x << 40) & 0x00FF000000000000) | ((x << 24) & 0x0000FF0000000000) | - ((x << 8) & 0x000000FF00000000) | ((x >> 8) & 0x00000000FF000000) | - ((x >> 24) & 0x0000000000FF0000) | ((x >> 40) & 0x000000000000FF00) | (x << 56); -} - -inline uint32_t bigswap(uint32_t x) -{ - return (x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24); -} - -inline uint16_t bigswap(uint16_t x) -{ - return (x >> 8) | (x << 8); -} - -#endif - -inline int64_t bigswap(int64_t x) -{ - return static_cast(bigswap(static_cast(x))); -} - -inline int32_t bigswap(int32_t x) -{ - return static_cast(bigswap(static_cast(x))); -} - -inline int16_t bigswap(int16_t x) -{ - return static_cast(bigswap(static_cast(x))); -} -} diff --git a/libraries/classparser/src/membuffer.h b/libraries/classparser/src/membuffer.h deleted file mode 100644 index f81c9705..00000000 --- a/libraries/classparser/src/membuffer.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "javaendian.h" - -namespace util -{ -class membuffer -{ -public: - membuffer(char *buffer, std::size_t size) - { - current = start = buffer; - end = start + size; - } - ~membuffer() - { - // maybe? possibly? left out to avoid confusion. for now. - // delete start; - } - /** - * Read some value. That's all ;) - */ - template void read(T &val) - { - val = *(T *)current; - current += sizeof(T); - } - /** - * Read a big-endian number - * valid for 2-byte, 4-byte and 8-byte variables - */ - template void read_be(T &val) - { - val = util::bigswap(*(T *)current); - current += sizeof(T); - } - /** - * Read a string in the format: - * 2B length (big endian, unsigned) - * length bytes data - */ - void read_jstr(std::string &str) - { - uint16_t length = 0; - read_be(length); - str.append(current, length); - current += length; - } - /** - * Skip N bytes - */ - void skip(std::size_t N) - { - current += N; - } - -private: - char *start, *end, *current; -}; -} diff --git a/libraries/xz-embedded/CMakeLists.txt b/libraries/xz-embedded/CMakeLists.txt deleted file mode 100644 index 4ce46102..00000000 --- a/libraries/xz-embedded/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.9.4) -project(xz-embedded LANGUAGES C) - -option(XZ_BUILD_BCJ "Build xz-embedded with BCJ support (native binary optimization)" OFF) -option(XZ_BUILD_CRC64 "Build xz-embedded with CRC64 checksum support" ON) -option(XZ_BUILD_MINIDEC "Build a tiny utility that decompresses xz streams" OFF) - -# See include/xz.h for manual feature configuration -# tweak this list and xz.h to fit your needs - -set(XZ_SOURCES - src/xz_crc32.c - src/xz_crc64.c - src/xz_dec_lzma2.c - src/xz_dec_stream.c -# src/xz_dec_bcj.c -) -add_library(xz-embedded STATIC ${XZ_SOURCES}) -target_include_directories(xz-embedded PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") -set_property(TARGET xz-embedded PROPERTY C_STANDARD 99) - -if(${XZ_BUILD_MINIDEC}) - add_executable(xzminidec xzminidec.c) - target_link_libraries(xzminidec xz-embedded) - set_property(TARGET xzminidec PROPERTY C_STANDARD 99) -endif() diff --git a/libraries/xz-embedded/include/xz.h b/libraries/xz-embedded/include/xz.h deleted file mode 100644 index 3779124c..00000000 --- a/libraries/xz-embedded/include/xz.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - * XZ decompressor - * - * Authors: Lasse Collin - * Igor Pavlov - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -#ifndef XZ_H -#define XZ_H - -#ifdef __KERNEL__ -#include -#include -#else -#include -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Definitions that determine available features */ -#define XZ_DEC_ANY_CHECK 1 -#define XZ_USE_CRC64 1 - -// native machine code compression stuff -/* -#define XZ_DEC_X86 -#define XZ_DEC_POWERPC -#define XZ_DEC_IA64 -#define XZ_DEC_ARM -#define XZ_DEC_ARMTHUMB -#define XZ_DEC_SPARC -*/ - -/* In Linux, this is used to make extern functions static when needed. */ -#ifndef XZ_EXTERN -#define XZ_EXTERN extern -#endif - -/** - * enum xz_mode - Operation mode - * - * @XZ_SINGLE: Single-call mode. This uses less RAM than - * than multi-call modes, because the LZMA2 - * dictionary doesn't need to be allocated as - * part of the decoder state. All required data - * structures are allocated at initialization, - * so xz_dec_run() cannot return XZ_MEM_ERROR. - * @XZ_PREALLOC: Multi-call mode with preallocated LZMA2 - * dictionary buffer. All data structures are - * allocated at initialization, so xz_dec_run() - * cannot return XZ_MEM_ERROR. - * @XZ_DYNALLOC: Multi-call mode. The LZMA2 dictionary is - * allocated once the required size has been - * parsed from the stream headers. If the - * allocation fails, xz_dec_run() will return - * XZ_MEM_ERROR. - * - * It is possible to enable support only for a subset of the above - * modes at compile time by defining XZ_DEC_SINGLE, XZ_DEC_PREALLOC, - * or XZ_DEC_DYNALLOC. The xz_dec kernel module is always compiled - * with support for all operation modes, but the preboot code may - * be built with fewer features to minimize code size. - */ -enum xz_mode -{ - XZ_SINGLE, - XZ_PREALLOC, - XZ_DYNALLOC -}; - -/** - * enum xz_ret - Return codes - * @XZ_OK: Everything is OK so far. More input or more - * output space is required to continue. This - * return code is possible only in multi-call mode - * (XZ_PREALLOC or XZ_DYNALLOC). - * @XZ_STREAM_END: Operation finished successfully. - * @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding - * is still possible in multi-call mode by simply - * calling xz_dec_run() again. - * Note that this return value is used only if - * XZ_DEC_ANY_CHECK was defined at build time, - * which is not used in the kernel. Unsupported - * check types return XZ_OPTIONS_ERROR if - * XZ_DEC_ANY_CHECK was not defined at build time. - * @XZ_MEM_ERROR: Allocating memory failed. This return code is - * possible only if the decoder was initialized - * with XZ_DYNALLOC. The amount of memory that was - * tried to be allocated was no more than the - * dict_max argument given to xz_dec_init(). - * @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than - * allowed by the dict_max argument given to - * xz_dec_init(). This return value is possible - * only in multi-call mode (XZ_PREALLOC or - * XZ_DYNALLOC); the single-call mode (XZ_SINGLE) - * ignores the dict_max argument. - * @XZ_FORMAT_ERROR: File format was not recognized (wrong magic - * bytes). - * @XZ_OPTIONS_ERROR: This implementation doesn't support the requested - * compression options. In the decoder this means - * that the header CRC32 matches, but the header - * itself specifies something that we don't support. - * @XZ_DATA_ERROR: Compressed data is corrupt. - * @XZ_BUF_ERROR: Cannot make any progress. Details are slightly - * different between multi-call and single-call - * mode; more information below. - * - * In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls - * to XZ code cannot consume any input and cannot produce any new output. - * This happens when there is no new input available, or the output buffer - * is full while at least one output byte is still pending. Assuming your - * code is not buggy, you can get this error only when decoding a compressed - * stream that is truncated or otherwise corrupt. - * - * In single-call mode, XZ_BUF_ERROR is returned only when the output buffer - * is too small or the compressed input is corrupt in a way that makes the - * decoder produce more output than the caller expected. When it is - * (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR - * is used instead of XZ_BUF_ERROR. - */ -enum xz_ret -{ - XZ_OK, - XZ_STREAM_END, - XZ_UNSUPPORTED_CHECK, - XZ_MEM_ERROR, - XZ_MEMLIMIT_ERROR, - XZ_FORMAT_ERROR, - XZ_OPTIONS_ERROR, - XZ_DATA_ERROR, - XZ_BUF_ERROR -}; - -/** - * struct xz_buf - Passing input and output buffers to XZ code - * @in: Beginning of the input buffer. This may be NULL if and only - * if in_pos is equal to in_size. - * @in_pos: Current position in the input buffer. This must not exceed - * in_size. - * @in_size: Size of the input buffer - * @out: Beginning of the output buffer. This may be NULL if and only - * if out_pos is equal to out_size. - * @out_pos: Current position in the output buffer. This must not exceed - * out_size. - * @out_size: Size of the output buffer - * - * Only the contents of the output buffer from out[out_pos] onward, and - * the variables in_pos and out_pos are modified by the XZ code. - */ -struct xz_buf -{ - const uint8_t *in; - size_t in_pos; - size_t in_size; - - uint8_t *out; - size_t out_pos; - size_t out_size; -}; - -/** - * struct xz_dec - Opaque type to hold the XZ decoder state - */ -struct xz_dec; - -/** - * xz_dec_init() - Allocate and initialize a XZ decoder state - * @mode: Operation mode - * @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for - * multi-call decoding. This is ignored in single-call mode - * (mode == XZ_SINGLE). LZMA2 dictionary is always 2^n bytes - * or 2^n + 2^(n-1) bytes (the latter sizes are less common - * in practice), so other values for dict_max don't make sense. - * In the kernel, dictionary sizes of 64 KiB, 128 KiB, 256 KiB, - * 512 KiB, and 1 MiB are probably the only reasonable values, - * except for kernel and initramfs images where a bigger - * dictionary can be fine and useful. - * - * Single-call mode (XZ_SINGLE): xz_dec_run() decodes the whole stream at - * once. The caller must provide enough output space or the decoding will - * fail. The output space is used as the dictionary buffer, which is why - * there is no need to allocate the dictionary as part of the decoder's - * internal state. - * - * Because the output buffer is used as the workspace, streams encoded using - * a big dictionary are not a problem in single-call mode. It is enough that - * the output buffer is big enough to hold the actual uncompressed data; it - * can be smaller than the dictionary size stored in the stream headers. - * - * Multi-call mode with preallocated dictionary (XZ_PREALLOC): dict_max bytes - * of memory is preallocated for the LZMA2 dictionary. This way there is no - * risk that xz_dec_run() could run out of memory, since xz_dec_run() will - * never allocate any memory. Instead, if the preallocated dictionary is too - * small for decoding the given input stream, xz_dec_run() will return - * XZ_MEMLIMIT_ERROR. Thus, it is important to know what kind of data will be - * decoded to avoid allocating excessive amount of memory for the dictionary. - * - * Multi-call mode with dynamically allocated dictionary (XZ_DYNALLOC): - * dict_max specifies the maximum allowed dictionary size that xz_dec_run() - * may allocate once it has parsed the dictionary size from the stream - * headers. This way excessive allocations can be avoided while still - * limiting the maximum memory usage to a sane value to prevent running the - * system out of memory when decompressing streams from untrusted sources. - * - * On success, xz_dec_init() returns a pointer to struct xz_dec, which is - * ready to be used with xz_dec_run(). If memory allocation fails, - * xz_dec_init() returns NULL. - */ -XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max); - -/** - * xz_dec_run() - Run the XZ decoder - * @s: Decoder state allocated using xz_dec_init() - * @b: Input and output buffers - * - * The possible return values depend on build options and operation mode. - * See enum xz_ret for details. - * - * Note that if an error occurs in single-call mode (return value is not - * XZ_STREAM_END), b->in_pos and b->out_pos are not modified and the - * contents of the output buffer from b->out[b->out_pos] onward are - * undefined. This is true even after XZ_BUF_ERROR, because with some filter - * chains, there may be a second pass over the output buffer, and this pass - * cannot be properly done if the output buffer is truncated. Thus, you - * cannot give the single-call decoder a too small buffer and then expect to - * get that amount valid data from the beginning of the stream. You must use - * the multi-call decoder if you don't want to uncompress the whole stream. - */ -XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b); - -/** - * xz_dec_reset() - Reset an already allocated decoder state - * @s: Decoder state allocated using xz_dec_init() - * - * This function can be used to reset the multi-call decoder state without - * freeing and reallocating memory with xz_dec_end() and xz_dec_init(). - * - * In single-call mode, xz_dec_reset() is always called in the beginning of - * xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in - * multi-call mode. - */ -XZ_EXTERN void xz_dec_reset(struct xz_dec *s); - -/** - * xz_dec_end() - Free the memory allocated for the decoder state - * @s: Decoder state allocated using xz_dec_init(). If s is NULL, - * this function does nothing. - */ -XZ_EXTERN void xz_dec_end(struct xz_dec *s); - -/* - * Standalone build (userspace build or in-kernel build for boot time use) - * needs a CRC32 implementation. For normal in-kernel use, kernel's own - * CRC32 module is used instead, and users of this module don't need to - * care about the functions below. - */ -#ifndef XZ_INTERNAL_CRC32 -#ifdef __KERNEL__ -#define XZ_INTERNAL_CRC32 0 -#else -#define XZ_INTERNAL_CRC32 1 -#endif -#endif - -/* - * If CRC64 support has been enabled with XZ_USE_CRC64, a CRC64 - * implementation is needed too. - */ -#ifndef XZ_USE_CRC64 -#undef XZ_INTERNAL_CRC64 -#define XZ_INTERNAL_CRC64 0 -#endif -#ifndef XZ_INTERNAL_CRC64 -#ifdef __KERNEL__ -#error Using CRC64 in the kernel has not been implemented. -#else -#define XZ_INTERNAL_CRC64 1 -#endif -#endif - -#if XZ_INTERNAL_CRC32 -/* - * This must be called before any other xz_* function to initialize - * the CRC32 lookup table. - */ -XZ_EXTERN void xz_crc32_init(void); - -/* - * Update CRC32 value using the polynomial from IEEE-802.3. To start a new - * calculation, the third argument must be zero. To continue the calculation, - * the previously returned value is passed as the third argument. - */ -XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc); -#endif - -#if XZ_INTERNAL_CRC64 -/* - * This must be called before any other xz_* function (except xz_crc32_init()) - * to initialize the CRC64 lookup table. - */ -XZ_EXTERN void xz_crc64_init(void); - -/* - * Update CRC64 value using the polynomial from ECMA-182. To start a new - * calculation, the third argument must be zero. To continue the calculation, - * the previously returned value is passed as the third argument. - */ -XZ_EXTERN uint64_t xz_crc64(const uint8_t *buf, size_t size, uint64_t crc); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libraries/xz-embedded/src/xz_config.h b/libraries/xz-embedded/src/xz_config.h deleted file mode 100644 index effdb1bd..00000000 --- a/libraries/xz-embedded/src/xz_config.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Private includes and definitions for userspace use of XZ Embedded - * - * Author: Lasse Collin - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -#ifndef XZ_CONFIG_H -#define XZ_CONFIG_H - -/* Uncomment to enable CRC64 support. */ -/* #define XZ_USE_CRC64 */ - -/* Uncomment as needed to enable BCJ filter decoders. */ -/* #define XZ_DEC_X86 */ -/* #define XZ_DEC_POWERPC */ -/* #define XZ_DEC_IA64 */ -/* #define XZ_DEC_ARM */ -/* #define XZ_DEC_ARMTHUMB */ -/* #define XZ_DEC_SPARC */ - -/* - * MSVC doesn't support modern C but XZ Embedded is mostly C89 - * so these are enough. - */ -#ifdef _MSC_VER -typedef unsigned char bool; -#define true 1 -#define false 0 -#define inline __inline -#else -#include -#endif - -#include -#include - -#include "xz.h" - -#define kmalloc(size, flags) malloc(size) -#define kfree(ptr) free(ptr) -#define vmalloc(size) malloc(size) -#define vfree(ptr) free(ptr) - -#define memeq(a, b, size) (memcmp(a, b, size) == 0) -#define memzero(buf, size) memset(buf, 0, size) - -#ifndef min -#define min(x, y) ((x) < (y) ? (x) : (y)) -#endif -#define min_t(type, x, y) min(x, y) - -/* - * Some functions have been marked with __always_inline to keep the - * performance reasonable even when the compiler is optimizing for - * small code size. You may be able to save a few bytes by #defining - * __always_inline to plain inline, but don't complain if the code - * becomes slow. - * - * NOTE: System headers on GNU/Linux may #define this macro already, - * so if you want to change it, you need to #undef it first. - */ -#ifndef __always_inline -#ifdef __GNUC__ -#define __always_inline inline __attribute__((__always_inline__)) -#else -#define __always_inline inline -#endif -#endif - -/* Inline functions to access unaligned unsigned 32-bit integers */ -#ifndef get_unaligned_le32 -static inline uint32_t get_unaligned_le32(const uint8_t *buf) -{ - return (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2] << 16) | - ((uint32_t)buf[3] << 24); -} -#endif - -#ifndef get_unaligned_be32 -static inline uint32_t get_unaligned_be32(const uint8_t *buf) -{ - return (uint32_t)(buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | - (uint32_t)buf[3]; -} -#endif - -#ifndef put_unaligned_le32 -static inline void put_unaligned_le32(uint32_t val, uint8_t *buf) -{ - buf[0] = (uint8_t)val; - buf[1] = (uint8_t)(val >> 8); - buf[2] = (uint8_t)(val >> 16); - buf[3] = (uint8_t)(val >> 24); -} -#endif - -#ifndef put_unaligned_be32 -static inline void put_unaligned_be32(uint32_t val, uint8_t *buf) -{ - buf[0] = (uint8_t)(val >> 24); - buf[1] = (uint8_t)(val >> 16); - buf[2] = (uint8_t)(val >> 8); - buf[3] = (uint8_t)val; -} -#endif - -/* - * Use get_unaligned_le32() also for aligned access for simplicity. On - * little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr)) - * could save a few bytes in code size. - */ -#ifndef get_le32 -#define get_le32 get_unaligned_le32 -#endif - -#endif diff --git a/libraries/xz-embedded/src/xz_crc32.c b/libraries/xz-embedded/src/xz_crc32.c deleted file mode 100644 index 65d9d5b8..00000000 --- a/libraries/xz-embedded/src/xz_crc32.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * CRC32 using the polynomial from IEEE-802.3 - * - * Authors: Lasse Collin - * Igor Pavlov - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -/* - * This is not the fastest implementation, but it is pretty compact. - * The fastest versions of xz_crc32() on modern CPUs without hardware - * accelerated CRC instruction are 3-5 times as fast as this version, - * but they are bigger and use more memory for the lookup table. - */ - -#include "xz_private.h" - -/* - * STATIC_RW_DATA is used in the pre-boot environment on some architectures. - * See for details. - */ -#ifndef STATIC_RW_DATA -#define STATIC_RW_DATA static -#endif - -STATIC_RW_DATA uint32_t xz_crc32_table[256]; - -XZ_EXTERN void xz_crc32_init(void) -{ - const uint32_t poly = 0xEDB88320; - - uint32_t i; - uint32_t j; - uint32_t r; - - for (i = 0; i < 256; ++i) - { - r = i; - for (j = 0; j < 8; ++j) - r = (r >> 1) ^ (poly & ~((r & 1) - 1)); - - xz_crc32_table[i] = r; - } - - return; -} - -XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) -{ - crc = ~crc; - - while (size != 0) - { - crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); - --size; - } - - return ~crc; -} diff --git a/libraries/xz-embedded/src/xz_crc64.c b/libraries/xz-embedded/src/xz_crc64.c deleted file mode 100644 index 0f711d8d..00000000 --- a/libraries/xz-embedded/src/xz_crc64.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * CRC64 using the polynomial from ECMA-182 - * - * This file is similar to xz_crc32.c. See the comments there. - * - * Authors: Lasse Collin - * Igor Pavlov - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -#include "xz_private.h" - -#ifndef STATIC_RW_DATA -#define STATIC_RW_DATA static -#endif - -STATIC_RW_DATA uint64_t xz_crc64_table[256]; - -XZ_EXTERN void xz_crc64_init(void) -{ - const uint64_t poly = 0xC96C5795D7870F42; - - uint32_t i; - uint32_t j; - uint64_t r; - - for (i = 0; i < 256; ++i) - { - r = i; - for (j = 0; j < 8; ++j) - r = (r >> 1) ^ (poly & ~((r & 1) - 1)); - - xz_crc64_table[i] = r; - } - - return; -} - -XZ_EXTERN uint64_t xz_crc64(const uint8_t *buf, size_t size, uint64_t crc) -{ - crc = ~crc; - - while (size != 0) - { - crc = xz_crc64_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); - --size; - } - - return ~crc; -} diff --git a/libraries/xz-embedded/src/xz_dec_bcj.c b/libraries/xz-embedded/src/xz_dec_bcj.c deleted file mode 100644 index a79fa76d..00000000 --- a/libraries/xz-embedded/src/xz_dec_bcj.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Branch/Call/Jump (BCJ) filter decoders - * - * Authors: Lasse Collin - * Igor Pavlov - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -#include "xz_private.h" - -/* - * The rest of the file is inside this ifdef. It makes things a little more - * convenient when building without support for any BCJ filters. - */ -#ifdef XZ_DEC_BCJ - -struct xz_dec_bcj -{ - /* Type of the BCJ filter being used */ - enum - { - BCJ_X86 = 4, /* x86 or x86-64 */ - BCJ_POWERPC = 5, /* Big endian only */ - BCJ_IA64 = 6, /* Big or little endian */ - BCJ_ARM = 7, /* Little endian only */ - BCJ_ARMTHUMB = 8, /* Little endian only */ - BCJ_SPARC = 9 /* Big or little endian */ - } type; - - /* - * Return value of the next filter in the chain. We need to preserve - * this information across calls, because we must not call the next - * filter anymore once it has returned XZ_STREAM_END. - */ - enum xz_ret ret; - - /* True if we are operating in single-call mode. */ - bool single_call; - - /* - * Absolute position relative to the beginning of the uncompressed - * data (in a single .xz Block). We care only about the lowest 32 - * bits so this doesn't need to be uint64_t even with big files. - */ - uint32_t pos; - - /* x86 filter state */ - uint32_t x86_prev_mask; - - /* Temporary space to hold the variables from struct xz_buf */ - uint8_t *out; - size_t out_pos; - size_t out_size; - - struct - { - /* Amount of already filtered data in the beginning of buf */ - size_t filtered; - - /* Total amount of data currently stored in buf */ - size_t size; - - /* - * Buffer to hold a mix of filtered and unfiltered data. This - * needs to be big enough to hold Alignment + 2 * Look-ahead: - * - * Type Alignment Look-ahead - * x86 1 4 - * PowerPC 4 0 - * IA-64 16 0 - * ARM 4 0 - * ARM-Thumb 2 2 - * SPARC 4 0 - */ - uint8_t buf[16]; - } temp; -}; - -#ifdef XZ_DEC_X86 -/* - * This is used to test the most significant byte of a memory address - * in an x86 instruction. - */ -static inline int bcj_x86_test_msbyte(uint8_t b) -{ - return b == 0x00 || b == 0xFF; -} - -static size_t bcj_x86(struct xz_dec_bcj *s, uint8_t *buf, size_t size) -{ - static const bool mask_to_allowed_status[8] = {true, true, true, false, - true, false, false, false}; - - static const uint8_t mask_to_bit_num[8] = {0, 1, 2, 2, 3, 3, 3, 3}; - - size_t i; - size_t prev_pos = (size_t) - 1; - uint32_t prev_mask = s->x86_prev_mask; - uint32_t src; - uint32_t dest; - uint32_t j; - uint8_t b; - - if (size <= 4) - return 0; - - size -= 4; - for (i = 0; i < size; ++i) - { - if ((buf[i] & 0xFE) != 0xE8) - continue; - - prev_pos = i - prev_pos; - if (prev_pos > 3) - { - prev_mask = 0; - } - else - { - prev_mask = (prev_mask << (prev_pos - 1)) & 7; - if (prev_mask != 0) - { - b = buf[i + 4 - mask_to_bit_num[prev_mask]]; - if (!mask_to_allowed_status[prev_mask] || bcj_x86_test_msbyte(b)) - { - prev_pos = i; - prev_mask = (prev_mask << 1) | 1; - continue; - } - } - } - - prev_pos = i; - - if (bcj_x86_test_msbyte(buf[i + 4])) - { - src = get_unaligned_le32(buf + i + 1); - while (true) - { - dest = src - (s->pos + (uint32_t)i + 5); - if (prev_mask == 0) - break; - - j = mask_to_bit_num[prev_mask] * 8; - b = (uint8_t)(dest >> (24 - j)); - if (!bcj_x86_test_msbyte(b)) - break; - - src = dest ^ (((uint32_t)1 << (32 - j)) - 1); - } - - dest &= 0x01FFFFFF; - dest |= (uint32_t)0 - (dest & 0x01000000); - put_unaligned_le32(dest, buf + i + 1); - i += 4; - } - else - { - prev_mask = (prev_mask << 1) | 1; - } - } - - prev_pos = i - prev_pos; - s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1); - return i; -} -#endif - -#ifdef XZ_DEC_POWERPC -static size_t bcj_powerpc(struct xz_dec_bcj *s, uint8_t *buf, size_t size) -{ - size_t i; - uint32_t instr; - - for (i = 0; i + 4 <= size; i += 4) - { - instr = get_unaligned_be32(buf + i); - if ((instr & 0xFC000003) == 0x48000001) - { - instr &= 0x03FFFFFC; - instr -= s->pos + (uint32_t)i; - instr &= 0x03FFFFFC; - instr |= 0x48000001; - put_unaligned_be32(instr, buf + i); - } - } - - return i; -} -#endif - -#ifdef XZ_DEC_IA64 -static size_t bcj_ia64(struct xz_dec_bcj *s, uint8_t *buf, size_t size) -{ - static const uint8_t branch_table[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0}; - - /* - * The local variables take a little bit stack space, but it's less - * than what LZMA2 decoder takes, so it doesn't make sense to reduce - * stack usage here without doing that for the LZMA2 decoder too. - */ - - /* Loop counters */ - size_t i; - size_t j; - - /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */ - uint32_t slot; - - /* Bitwise offset of the instruction indicated by slot */ - uint32_t bit_pos; - - /* bit_pos split into byte and bit parts */ - uint32_t byte_pos; - uint32_t bit_res; - - /* Address part of an instruction */ - uint32_t addr; - - /* Mask used to detect which instructions to convert */ - uint32_t mask; - - /* 41-bit instruction stored somewhere in the lowest 48 bits */ - uint64_t instr; - - /* Instruction normalized with bit_res for easier manipulation */ - uint64_t norm; - - for (i = 0; i + 16 <= size; i += 16) - { - mask = branch_table[buf[i] & 0x1F]; - for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) - { - if (((mask >> slot) & 1) == 0) - continue; - - byte_pos = bit_pos >> 3; - bit_res = bit_pos & 7; - instr = 0; - for (j = 0; j < 6; ++j) - instr |= (uint64_t)(buf[i + j + byte_pos]) << (8 * j); - - norm = instr >> bit_res; - - if (((norm >> 37) & 0x0F) == 0x05 && ((norm >> 9) & 0x07) == 0) - { - addr = (norm >> 13) & 0x0FFFFF; - addr |= ((uint32_t)(norm >> 36) & 1) << 20; - addr <<= 4; - addr -= s->pos + (uint32_t)i; - addr >>= 4; - - norm &= ~((uint64_t)0x8FFFFF << 13); - norm |= (uint64_t)(addr & 0x0FFFFF) << 13; - norm |= (uint64_t)(addr & 0x100000) << (36 - 20); - - instr &= (1 << bit_res) - 1; - instr |= norm << bit_res; - - for (j = 0; j < 6; j++) - buf[i + j + byte_pos] = (uint8_t)(instr >> (8 * j)); - } - } - } - - return i; -} -#endif - -#ifdef XZ_DEC_ARM -static size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size) -{ - size_t i; - uint32_t addr; - - for (i = 0; i + 4 <= size; i += 4) - { - if (buf[i + 3] == 0xEB) - { - addr = - (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8) | ((uint32_t)buf[i + 2] << 16); - addr <<= 2; - addr -= s->pos + (uint32_t)i + 8; - addr >>= 2; - buf[i] = (uint8_t)addr; - buf[i + 1] = (uint8_t)(addr >> 8); - buf[i + 2] = (uint8_t)(addr >> 16); - } - } - - return i; -} -#endif - -#ifdef XZ_DEC_ARMTHUMB -static size_t bcj_armthumb(struct xz_dec_bcj *s, uint8_t *buf, size_t size) -{ - size_t i; - uint32_t addr; - - for (i = 0; i + 4 <= size; i += 2) - { - if ((buf[i + 1] & 0xF8) == 0xF0 && (buf[i + 3] & 0xF8) == 0xF8) - { - addr = (((uint32_t)buf[i + 1] & 0x07) << 19) | ((uint32_t)buf[i] << 11) | - (((uint32_t)buf[i + 3] & 0x07) << 8) | (uint32_t)buf[i + 2]; - addr <<= 1; - addr -= s->pos + (uint32_t)i + 4; - addr >>= 1; - buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07)); - buf[i] = (uint8_t)(addr >> 11); - buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07)); - buf[i + 2] = (uint8_t)addr; - i += 2; - } - } - - return i; -} -#endif - -#ifdef XZ_DEC_SPARC -static size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size) -{ - size_t i; - uint32_t instr; - - for (i = 0; i + 4 <= size; i += 4) - { - instr = get_unaligned_be32(buf + i); - if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) - { - instr <<= 2; - instr -= s->pos + (uint32_t)i; - instr >>= 2; - instr = - ((uint32_t)0x40000000 - (instr & 0x400000)) | 0x40000000 | (instr & 0x3FFFFF); - put_unaligned_be32(instr, buf + i); - } - } - - return i; -} -#endif - -/* - * Apply the selected BCJ filter. Update *pos and s->pos to match the amount - * of data that got filtered. - * - * NOTE: This is implemented as a switch statement to avoid using function - * pointers, which could be problematic in the kernel boot code, which must - * avoid pointers to static data (at least on x86). - */ -static void bcj_apply(struct xz_dec_bcj *s, uint8_t *buf, size_t *pos, size_t size) -{ - size_t filtered; - - buf += *pos; - size -= *pos; - - switch (s->type) - { -#ifdef XZ_DEC_X86 - case BCJ_X86: - filtered = bcj_x86(s, buf, size); - break; -#endif -#ifdef XZ_DEC_POWERPC - case BCJ_POWERPC: - filtered = bcj_powerpc(s, buf, size); - break; -#endif -#ifdef XZ_DEC_IA64 - case BCJ_IA64: - filtered = bcj_ia64(s, buf, size); - break; -#endif -#ifdef XZ_DEC_ARM - case BCJ_ARM: - filtered = bcj_arm(s, buf, size); - break; -#endif -#ifdef XZ_DEC_ARMTHUMB - case BCJ_ARMTHUMB: - filtered = bcj_armthumb(s, buf, size); - break; -#endif -#ifdef XZ_DEC_SPARC - case BCJ_SPARC: - filtered = bcj_sparc(s, buf, size); - break; -#endif - default: - /* Never reached but silence compiler warnings. */ - filtered = 0; - break; - } - - *pos += filtered; - s->pos += filtered; -} - -/* - * Flush pending filtered data from temp to the output buffer. - * Move the remaining mixture of possibly filtered and unfiltered - * data to the beginning of temp. - */ -static void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b) -{ - size_t copy_size; - - copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos); - memcpy(b->out + b->out_pos, s->temp.buf, copy_size); - b->out_pos += copy_size; - - s->temp.filtered -= copy_size; - s->temp.size -= copy_size; - memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size); -} - -/* - * The BCJ filter functions are primitive in sense that they process the - * data in chunks of 1-16 bytes. To hide this issue, this function does - * some buffering. - */ -XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, struct xz_dec_lzma2 *lzma2, - struct xz_buf *b) -{ - size_t out_start; - - /* - * Flush pending already filtered data to the output buffer. Return - * immediatelly if we couldn't flush everything, or if the next - * filter in the chain had already returned XZ_STREAM_END. - */ - if (s->temp.filtered > 0) - { - bcj_flush(s, b); - if (s->temp.filtered > 0) - return XZ_OK; - - if (s->ret == XZ_STREAM_END) - return XZ_STREAM_END; - } - - /* - * If we have more output space than what is currently pending in - * temp, copy the unfiltered data from temp to the output buffer - * and try to fill the output buffer by decoding more data from the - * next filter in the chain. Apply the BCJ filter on the new data - * in the output buffer. If everything cannot be filtered, copy it - * to temp and rewind the output buffer position accordingly. - * - * This needs to be always run when temp.size == 0 to handle a special - * case where the output buffer is full and the next filter has no - * more output coming but hasn't returned XZ_STREAM_END yet. - */ - if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) - { - out_start = b->out_pos; - memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); - b->out_pos += s->temp.size; - - s->ret = xz_dec_lzma2_run(lzma2, b); - if (s->ret != XZ_STREAM_END && (s->ret != XZ_OK || s->single_call)) - return s->ret; - - bcj_apply(s, b->out, &out_start, b->out_pos); - - /* - * As an exception, if the next filter returned XZ_STREAM_END, - * we can do that too, since the last few bytes that remain - * unfiltered are meant to remain unfiltered. - */ - if (s->ret == XZ_STREAM_END) - return XZ_STREAM_END; - - s->temp.size = b->out_pos - out_start; - b->out_pos -= s->temp.size; - memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); - - /* - * If there wasn't enough input to the next filter to fill - * the output buffer with unfiltered data, there's no point - * to try decoding more data to temp. - */ - if (b->out_pos + s->temp.size < b->out_size) - return XZ_OK; - } - - /* - * We have unfiltered data in temp. If the output buffer isn't full - * yet, try to fill the temp buffer by decoding more data from the - * next filter. Apply the BCJ filter on temp. Then we hopefully can - * fill the actual output buffer by copying filtered data from temp. - * A mix of filtered and unfiltered data may be left in temp; it will - * be taken care on the next call to this function. - */ - if (b->out_pos < b->out_size) - { - /* Make b->out{,_pos,_size} temporarily point to s->temp. */ - s->out = b->out; - s->out_pos = b->out_pos; - s->out_size = b->out_size; - b->out = s->temp.buf; - b->out_pos = s->temp.size; - b->out_size = sizeof(s->temp.buf); - - s->ret = xz_dec_lzma2_run(lzma2, b); - - s->temp.size = b->out_pos; - b->out = s->out; - b->out_pos = s->out_pos; - b->out_size = s->out_size; - - if (s->ret != XZ_OK && s->ret != XZ_STREAM_END) - return s->ret; - - bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size); - - /* - * If the next filter returned XZ_STREAM_END, we mark that - * everything is filtered, since the last unfiltered bytes - * of the stream are meant to be left as is. - */ - if (s->ret == XZ_STREAM_END) - s->temp.filtered = s->temp.size; - - bcj_flush(s, b); - if (s->temp.filtered > 0) - return XZ_OK; - } - - return s->ret; -} - -XZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call) -{ - struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL); - if (s != NULL) - s->single_call = single_call; - - return s; -} - -XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id) -{ - switch (id) - { -#ifdef XZ_DEC_X86 - case BCJ_X86: -#endif -#ifdef XZ_DEC_POWERPC - case BCJ_POWERPC: -#endif -#ifdef XZ_DEC_IA64 - case BCJ_IA64: -#endif -#ifdef XZ_DEC_ARM - case BCJ_ARM: -#endif -#ifdef XZ_DEC_ARMTHUMB - case BCJ_ARMTHUMB: -#endif -#ifdef XZ_DEC_SPARC - case BCJ_SPARC: -#endif - break; - - default: - /* Unsupported Filter ID */ - return XZ_OPTIONS_ERROR; - } - - s->type = id; - s->ret = XZ_OK; - s->pos = 0; - s->x86_prev_mask = 0; - s->temp.filtered = 0; - s->temp.size = 0; - - return XZ_OK; -} - -#endif diff --git a/libraries/xz-embedded/src/xz_dec_lzma2.c b/libraries/xz-embedded/src/xz_dec_lzma2.c deleted file mode 100644 index 365ace2b..00000000 --- a/libraries/xz-embedded/src/xz_dec_lzma2.c +++ /dev/null @@ -1,1231 +0,0 @@ -/* - * LZMA2 decoder - * - * Authors: Lasse Collin - * Igor Pavlov - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -#include "xz_private.h" -#include "xz_lzma2.h" - -/* - * Range decoder initialization eats the first five bytes of each LZMA chunk. - */ -#define RC_INIT_BYTES 5 - -/* - * Minimum number of usable input buffer to safely decode one LZMA symbol. - * The worst case is that we decode 22 bits using probabilities and 26 - * direct bits. This may decode at maximum of 20 bytes of input. However, - * lzma_main() does an extra normalization before returning, thus we - * need to put 21 here. - */ -#define LZMA_IN_REQUIRED 21 - -/* - * Dictionary (history buffer) - * - * These are always true: - * start <= pos <= full <= end - * pos <= limit <= end - * - * In multi-call mode, also these are true: - * end == size - * size <= size_max - * allocated <= size - * - * Most of these variables are size_t to support single-call mode, - * in which the dictionary variables address the actual output - * buffer directly. - */ -struct dictionary -{ - /* Beginning of the history buffer */ - uint8_t *buf; - - /* Old position in buf (before decoding more data) */ - size_t start; - - /* Position in buf */ - size_t pos; - - /* - * How full dictionary is. This is used to detect corrupt input that - * would read beyond the beginning of the uncompressed stream. - */ - size_t full; - - /* Write limit; we don't write to buf[limit] or later bytes. */ - size_t limit; - - /* - * End of the dictionary buffer. In multi-call mode, this is - * the same as the dictionary size. In single-call mode, this - * indicates the size of the output buffer. - */ - size_t end; - - /* - * Size of the dictionary as specified in Block Header. This is used - * together with "full" to detect corrupt input that would make us - * read beyond the beginning of the uncompressed stream. - */ - uint32_t size; - - /* - * Maximum allowed dictionary size in multi-call mode. - * This is ignored in single-call mode. - */ - uint32_t size_max; - - /* - * Amount of memory currently allocated for the dictionary. - * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC, - * size_max is always the same as the allocated size.) - */ - uint32_t allocated; - - /* Operation mode */ - enum xz_mode mode; -}; - -/* Range decoder */ -struct rc_dec -{ - uint32_t range; - uint32_t code; - - /* - * Number of initializing bytes remaining to be read - * by rc_read_init(). - */ - uint32_t init_bytes_left; - - /* - * Buffer from which we read our input. It can be either - * temp.buf or the caller-provided input buffer. - */ - const uint8_t *in; - size_t in_pos; - size_t in_limit; -}; - -/* Probabilities for a length decoder. */ -struct lzma_len_dec -{ - /* Probability of match length being at least 10 */ - uint16_t choice; - - /* Probability of match length being at least 18 */ - uint16_t choice2; - - /* Probabilities for match lengths 2-9 */ - uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; - - /* Probabilities for match lengths 10-17 */ - uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; - - /* Probabilities for match lengths 18-273 */ - uint16_t high[LEN_HIGH_SYMBOLS]; -}; - -struct lzma_dec -{ - /* Distances of latest four matches */ - uint32_t rep0; - uint32_t rep1; - uint32_t rep2; - uint32_t rep3; - - /* Types of the most recently seen LZMA symbols */ - enum lzma_state state; - - /* - * Length of a match. This is updated so that dict_repeat can - * be called again to finish repeating the whole match. - */ - uint32_t len; - - /* - * LZMA properties or related bit masks (number of literal - * context bits, a mask dervied from the number of literal - * position bits, and a mask dervied from the number - * position bits) - */ - uint32_t lc; - uint32_t literal_pos_mask; /* (1 << lp) - 1 */ - uint32_t pos_mask; /* (1 << pb) - 1 */ - - /* If 1, it's a match. Otherwise it's a single 8-bit literal. */ - uint16_t is_match[STATES][POS_STATES_MAX]; - - /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */ - uint16_t is_rep[STATES]; - - /* - * If 0, distance of a repeated match is rep0. - * Otherwise check is_rep1. - */ - uint16_t is_rep0[STATES]; - - /* - * If 0, distance of a repeated match is rep1. - * Otherwise check is_rep2. - */ - uint16_t is_rep1[STATES]; - - /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */ - uint16_t is_rep2[STATES]; - - /* - * If 1, the repeated match has length of one byte. Otherwise - * the length is decoded from rep_len_decoder. - */ - uint16_t is_rep0_long[STATES][POS_STATES_MAX]; - - /* - * Probability tree for the highest two bits of the match - * distance. There is a separate probability tree for match - * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273]. - */ - uint16_t dist_slot[DIST_STATES][DIST_SLOTS]; - - /* - * Probility trees for additional bits for match distance - * when the distance is in the range [4, 127]. - */ - uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END]; - - /* - * Probability tree for the lowest four bits of a match - * distance that is equal to or greater than 128. - */ - uint16_t dist_align[ALIGN_SIZE]; - - /* Length of a normal match */ - struct lzma_len_dec match_len_dec; - - /* Length of a repeated match */ - struct lzma_len_dec rep_len_dec; - - /* Probabilities of literals */ - uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; -}; - -struct lzma2_dec -{ - /* Position in xz_dec_lzma2_run(). */ - enum lzma2_seq - { - SEQ_CONTROL, - SEQ_UNCOMPRESSED_1, - SEQ_UNCOMPRESSED_2, - SEQ_COMPRESSED_0, - SEQ_COMPRESSED_1, - SEQ_PROPERTIES, - SEQ_LZMA_PREPARE, - SEQ_LZMA_RUN, - SEQ_COPY - } sequence; - - /* Next position after decoding the compressed size of the chunk. */ - enum lzma2_seq next_sequence; - - /* Uncompressed size of LZMA chunk (2 MiB at maximum) */ - uint32_t uncompressed; - - /* - * Compressed size of LZMA chunk or compressed/uncompressed - * size of uncompressed chunk (64 KiB at maximum) - */ - uint32_t compressed; - - /* - * True if dictionary reset is needed. This is false before - * the first chunk (LZMA or uncompressed). - */ - bool need_dict_reset; - - /* - * True if new LZMA properties are needed. This is false - * before the first LZMA chunk. - */ - bool need_props; -}; - -struct xz_dec_lzma2 -{ - /* - * The order below is important on x86 to reduce code size and - * it shouldn't hurt on other platforms. Everything up to and - * including lzma.pos_mask are in the first 128 bytes on x86-32, - * which allows using smaller instructions to access those - * variables. On x86-64, fewer variables fit into the first 128 - * bytes, but this is still the best order without sacrificing - * the readability by splitting the structures. - */ - struct rc_dec rc; - struct dictionary dict; - struct lzma2_dec lzma2; - struct lzma_dec lzma; - - /* - * Temporary buffer which holds small number of input bytes between - * decoder calls. See lzma2_lzma() for details. - */ - struct - { - uint32_t size; - uint8_t buf[3 * LZMA_IN_REQUIRED]; - } temp; -}; - -/************** - * Dictionary * - **************/ - -/* - * Reset the dictionary state. When in single-call mode, set up the beginning - * of the dictionary to point to the actual output buffer. - */ -static void dict_reset(struct dictionary *dict, struct xz_buf *b) -{ - if (DEC_IS_SINGLE(dict->mode)) - { - dict->buf = b->out + b->out_pos; - dict->end = b->out_size - b->out_pos; - } - - dict->start = 0; - dict->pos = 0; - dict->limit = 0; - dict->full = 0; -} - -/* Set dictionary write limit */ -static void dict_limit(struct dictionary *dict, size_t out_max) -{ - if (dict->end - dict->pos <= out_max) - dict->limit = dict->end; - else - dict->limit = dict->pos + out_max; -} - -/* Return true if at least one byte can be written into the dictionary. */ -static inline bool dict_has_space(const struct dictionary *dict) -{ - return dict->pos < dict->limit; -} - -/* - * Get a byte from the dictionary at the given distance. The distance is - * assumed to valid, or as a special case, zero when the dictionary is - * still empty. This special case is needed for single-call decoding to - * avoid writing a '\0' to the end of the destination buffer. - */ -static inline uint32_t dict_get(const struct dictionary *dict, uint32_t dist) -{ - size_t offset = dict->pos - dist - 1; - - if (dist >= dict->pos) - offset += dict->end; - - return dict->full > 0 ? dict->buf[offset] : 0; -} - -/* - * Put one byte into the dictionary. It is assumed that there is space for it. - */ -static inline void dict_put(struct dictionary *dict, uint8_t byte) -{ - dict->buf[dict->pos++] = byte; - - if (dict->full < dict->pos) - dict->full = dict->pos; -} - -/* - * Repeat given number of bytes from the given distance. If the distance is - * invalid, false is returned. On success, true is returned and *len is - * updated to indicate how many bytes were left to be repeated. - */ -static bool dict_repeat(struct dictionary *dict, uint32_t *len, uint32_t dist) -{ - size_t back; - uint32_t left; - - if (dist >= dict->full || dist >= dict->size) - return false; - - left = min_t(size_t, dict->limit - dict->pos, *len); - *len -= left; - - back = dict->pos - dist - 1; - if (dist >= dict->pos) - back += dict->end; - - do - { - dict->buf[dict->pos++] = dict->buf[back++]; - if (back == dict->end) - back = 0; - } while (--left > 0); - - if (dict->full < dict->pos) - dict->full = dict->pos; - - return true; -} - -/* Copy uncompressed data as is from input to dictionary and output buffers. */ -static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, uint32_t *left) -{ - size_t copy_size; - - while (*left > 0 && b->in_pos < b->in_size && b->out_pos < b->out_size) - { - copy_size = min(b->in_size - b->in_pos, b->out_size - b->out_pos); - if (copy_size > dict->end - dict->pos) - copy_size = dict->end - dict->pos; - if (copy_size > *left) - copy_size = *left; - - *left -= copy_size; - - memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); - dict->pos += copy_size; - - if (dict->full < dict->pos) - dict->full = dict->pos; - - if (DEC_IS_MULTI(dict->mode)) - { - if (dict->pos == dict->end) - dict->pos = 0; - - memcpy(b->out + b->out_pos, b->in + b->in_pos, copy_size); - } - - dict->start = dict->pos; - - b->out_pos += copy_size; - b->in_pos += copy_size; - } -} - -/* - * Flush pending data from dictionary to b->out. It is assumed that there is - * enough space in b->out. This is guaranteed because caller uses dict_limit() - * before decoding data into the dictionary. - */ -static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) -{ - size_t copy_size = dict->pos - dict->start; - - if (DEC_IS_MULTI(dict->mode)) - { - if (dict->pos == dict->end) - dict->pos = 0; - - memcpy(b->out + b->out_pos, dict->buf + dict->start, copy_size); - } - - dict->start = dict->pos; - b->out_pos += copy_size; - return copy_size; -} - -/***************** - * Range decoder * - *****************/ - -/* Reset the range decoder. */ -static void rc_reset(struct rc_dec *rc) -{ - rc->range = (uint32_t) - 1; - rc->code = 0; - rc->init_bytes_left = RC_INIT_BYTES; -} - -/* - * Read the first five initial bytes into rc->code if they haven't been - * read already. (Yes, the first byte gets completely ignored.) - */ -static bool rc_read_init(struct rc_dec *rc, struct xz_buf *b) -{ - while (rc->init_bytes_left > 0) - { - if (b->in_pos == b->in_size) - return false; - - rc->code = (rc->code << 8) + b->in[b->in_pos++]; - --rc->init_bytes_left; - } - - return true; -} - -/* Return true if there may not be enough input for the next decoding loop. */ -static inline bool rc_limit_exceeded(const struct rc_dec *rc) -{ - return rc->in_pos > rc->in_limit; -} - -/* - * Return true if it is possible (from point of view of range decoder) that - * we have reached the end of the LZMA chunk. - */ -static inline bool rc_is_finished(const struct rc_dec *rc) -{ - return rc->code == 0; -} - -/* Read the next input byte if needed. */ -static __always_inline void rc_normalize(struct rc_dec *rc) -{ - if (rc->range < RC_TOP_VALUE) - { - rc->range <<= RC_SHIFT_BITS; - rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++]; - } -} - -/* - * Decode one bit. In some versions, this function has been splitted in three - * functions so that the compiler is supposed to be able to more easily avoid - * an extra branch. In this particular version of the LZMA decoder, this - * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 - * on x86). Using a non-splitted version results in nicer looking code too. - * - * NOTE: This must return an int. Do not make it return a bool or the speed - * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, - * and it generates 10-20 % faster code than GCC 3.x from this file anyway.) - */ -static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob) -{ - uint32_t bound; - int bit; - - rc_normalize(rc); - bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob; - if (rc->code < bound) - { - rc->range = bound; - *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS; - bit = 0; - } - else - { - rc->range -= bound; - rc->code -= bound; - *prob -= *prob >> RC_MOVE_BITS; - bit = 1; - } - - return bit; -} - -/* Decode a bittree starting from the most significant bit. */ -static __always_inline uint32_t rc_bittree(struct rc_dec *rc, uint16_t *probs, uint32_t limit) -{ - uint32_t symbol = 1; - - do - { - if (rc_bit(rc, &probs[symbol])) - symbol = (symbol << 1) + 1; - else - symbol <<= 1; - } while (symbol < limit); - - return symbol; -} - -/* Decode a bittree starting from the least significant bit. */ -static __always_inline void rc_bittree_reverse(struct rc_dec *rc, uint16_t *probs, - uint32_t *dest, uint32_t limit) -{ - uint32_t symbol = 1; - uint32_t i = 0; - - do - { - if (rc_bit(rc, &probs[symbol])) - { - symbol = (symbol << 1) + 1; - *dest += 1 << i; - } - else - { - symbol <<= 1; - } - } while (++i < limit); -} - -/* Decode direct bits (fixed fifty-fifty probability) */ -static inline void rc_direct(struct rc_dec *rc, uint32_t *dest, uint32_t limit) -{ - uint32_t mask; - - do - { - rc_normalize(rc); - rc->range >>= 1; - rc->code -= rc->range; - mask = (uint32_t)0 - (rc->code >> 31); - rc->code += rc->range & mask; - *dest = (*dest << 1) + (mask + 1); - } while (--limit > 0); -} - -/******** - * LZMA * - ********/ - -/* Get pointer to literal coder probability array. */ -static uint16_t *lzma_literal_probs(struct xz_dec_lzma2 *s) -{ - uint32_t prev_byte = dict_get(&s->dict, 0); - uint32_t low = prev_byte >> (8 - s->lzma.lc); - uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc; - return s->lzma.literal[low + high]; -} - -/* Decode a literal (one 8-bit byte) */ -static void lzma_literal(struct xz_dec_lzma2 *s) -{ - uint16_t *probs; - uint32_t symbol; - uint32_t match_byte; - uint32_t match_bit; - uint32_t offset; - uint32_t i; - - probs = lzma_literal_probs(s); - - if (lzma_state_is_literal(s->lzma.state)) - { - symbol = rc_bittree(&s->rc, probs, 0x100); - } - else - { - symbol = 1; - match_byte = dict_get(&s->dict, s->lzma.rep0) << 1; - offset = 0x100; - - do - { - match_bit = match_byte & offset; - match_byte <<= 1; - i = offset + match_bit + symbol; - - if (rc_bit(&s->rc, &probs[i])) - { - symbol = (symbol << 1) + 1; - offset &= match_bit; - } - else - { - symbol <<= 1; - offset &= ~match_bit; - } - } while (symbol < 0x100); - } - - dict_put(&s->dict, (uint8_t)symbol); - lzma_state_literal(&s->lzma.state); -} - -/* Decode the length of the match into s->lzma.len. */ -static void lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l, uint32_t pos_state) -{ - uint16_t *probs; - uint32_t limit; - - if (!rc_bit(&s->rc, &l->choice)) - { - probs = l->low[pos_state]; - limit = LEN_LOW_SYMBOLS; - s->lzma.len = MATCH_LEN_MIN; - } - else - { - if (!rc_bit(&s->rc, &l->choice2)) - { - probs = l->mid[pos_state]; - limit = LEN_MID_SYMBOLS; - s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; - } - else - { - probs = l->high; - limit = LEN_HIGH_SYMBOLS; - s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; - } - } - - s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit; -} - -/* Decode a match. The distance will be stored in s->lzma.rep0. */ -static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state) -{ - uint16_t *probs; - uint32_t dist_slot; - uint32_t limit; - - lzma_state_match(&s->lzma.state); - - s->lzma.rep3 = s->lzma.rep2; - s->lzma.rep2 = s->lzma.rep1; - s->lzma.rep1 = s->lzma.rep0; - - lzma_len(s, &s->lzma.match_len_dec, pos_state); - - probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)]; - dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS; - - if (dist_slot < DIST_MODEL_START) - { - s->lzma.rep0 = dist_slot; - } - else - { - limit = (dist_slot >> 1) - 1; - s->lzma.rep0 = 2 + (dist_slot & 1); - - if (dist_slot < DIST_MODEL_END) - { - s->lzma.rep0 <<= limit; - probs = s->lzma.dist_special + s->lzma.rep0 - dist_slot - 1; - rc_bittree_reverse(&s->rc, probs, &s->lzma.rep0, limit); - } - else - { - rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS); - s->lzma.rep0 <<= ALIGN_BITS; - rc_bittree_reverse(&s->rc, s->lzma.dist_align, &s->lzma.rep0, ALIGN_BITS); - } - } -} - -/* - * Decode a repeated match. The distance is one of the four most recently - * seen matches. The distance will be stored in s->lzma.rep0. - */ -static void lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state) -{ - uint32_t tmp; - - if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) - { - if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[s->lzma.state][pos_state])) - { - lzma_state_short_rep(&s->lzma.state); - s->lzma.len = 1; - return; - } - } - else - { - if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) - { - tmp = s->lzma.rep1; - } - else - { - if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) - { - tmp = s->lzma.rep2; - } - else - { - tmp = s->lzma.rep3; - s->lzma.rep3 = s->lzma.rep2; - } - - s->lzma.rep2 = s->lzma.rep1; - } - - s->lzma.rep1 = s->lzma.rep0; - s->lzma.rep0 = tmp; - } - - lzma_state_long_rep(&s->lzma.state); - lzma_len(s, &s->lzma.rep_len_dec, pos_state); -} - -/* LZMA decoder core */ -static bool lzma_main(struct xz_dec_lzma2 *s) -{ - uint32_t pos_state; - - /* - * If the dictionary was reached during the previous call, try to - * finish the possibly pending repeat in the dictionary. - */ - if (dict_has_space(&s->dict) && s->lzma.len > 0) - dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0); - - /* - * Decode more LZMA symbols. One iteration may consume up to - * LZMA_IN_REQUIRED - 1 bytes. - */ - while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) - { - pos_state = s->dict.pos & s->lzma.pos_mask; - - if (!rc_bit(&s->rc, &s->lzma.is_match[s->lzma.state][pos_state])) - { - lzma_literal(s); - } - else - { - if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state])) - lzma_rep_match(s, pos_state); - else - lzma_match(s, pos_state); - - if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0)) - return false; - } - } - - /* - * Having the range decoder always normalized when we are outside - * this function makes it easier to correctly handle end of the chunk. - */ - rc_normalize(&s->rc); - - return true; -} - -/* - * Reset the LZMA decoder and range decoder state. Dictionary is nore reset - * here, because LZMA state may be reset without resetting the dictionary. - */ -static void lzma_reset(struct xz_dec_lzma2 *s) -{ - uint16_t *probs; - size_t i; - - s->lzma.state = STATE_LIT_LIT; - s->lzma.rep0 = 0; - s->lzma.rep1 = 0; - s->lzma.rep2 = 0; - s->lzma.rep3 = 0; - - /* - * All probabilities are initialized to the same value. This hack - * makes the code smaller by avoiding a separate loop for each - * probability array. - * - * This could be optimized so that only that part of literal - * probabilities that are actually required. In the common case - * we would write 12 KiB less. - */ - probs = s->lzma.is_match[0]; - for (i = 0; i < PROBS_TOTAL; ++i) - probs[i] = RC_BIT_MODEL_TOTAL / 2; - - rc_reset(&s->rc); -} - -/* - * Decode and validate LZMA properties (lc/lp/pb) and calculate the bit masks - * from the decoded lp and pb values. On success, the LZMA decoder state is - * reset and true is returned. - */ -static bool lzma_props(struct xz_dec_lzma2 *s, uint8_t props) -{ - if (props > (4 * 5 + 4) * 9 + 8) - return false; - - s->lzma.pos_mask = 0; - while (props >= 9 * 5) - { - props -= 9 * 5; - ++s->lzma.pos_mask; - } - - s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1; - - s->lzma.literal_pos_mask = 0; - while (props >= 9) - { - props -= 9; - ++s->lzma.literal_pos_mask; - } - - s->lzma.lc = props; - - if (s->lzma.lc + s->lzma.literal_pos_mask > 4) - return false; - - s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1; - - lzma_reset(s); - - return true; -} - -/********* - * LZMA2 * - *********/ - -/* - * The LZMA decoder assumes that if the input limit (s->rc.in_limit) hasn't - * been exceeded, it is safe to read up to LZMA_IN_REQUIRED bytes. This - * wrapper function takes care of making the LZMA decoder's assumption safe. - * - * As long as there is plenty of input left to be decoded in the current LZMA - * chunk, we decode directly from the caller-supplied input buffer until - * there's LZMA_IN_REQUIRED bytes left. Those remaining bytes are copied into - * s->temp.buf, which (hopefully) gets filled on the next call to this - * function. We decode a few bytes from the temporary buffer so that we can - * continue decoding from the caller-supplied input buffer again. - */ -static bool lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b) -{ - size_t in_avail; - uint32_t tmp; - - in_avail = b->in_size - b->in_pos; - if (s->temp.size > 0 || s->lzma2.compressed == 0) - { - tmp = 2 * LZMA_IN_REQUIRED - s->temp.size; - if (tmp > s->lzma2.compressed - s->temp.size) - tmp = s->lzma2.compressed - s->temp.size; - if (tmp > in_avail) - tmp = in_avail; - - memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp); - - if (s->temp.size + tmp == s->lzma2.compressed) - { - memzero(s->temp.buf + s->temp.size + tmp, sizeof(s->temp.buf) - s->temp.size - tmp); - s->rc.in_limit = s->temp.size + tmp; - } - else if (s->temp.size + tmp < LZMA_IN_REQUIRED) - { - s->temp.size += tmp; - b->in_pos += tmp; - return true; - } - else - { - s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED; - } - - s->rc.in = s->temp.buf; - s->rc.in_pos = 0; - - if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp) - return false; - - s->lzma2.compressed -= s->rc.in_pos; - - if (s->rc.in_pos < s->temp.size) - { - s->temp.size -= s->rc.in_pos; - memmove(s->temp.buf, s->temp.buf + s->rc.in_pos, s->temp.size); - return true; - } - - b->in_pos += s->rc.in_pos - s->temp.size; - s->temp.size = 0; - } - - in_avail = b->in_size - b->in_pos; - if (in_avail >= LZMA_IN_REQUIRED) - { - s->rc.in = b->in; - s->rc.in_pos = b->in_pos; - - if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED) - s->rc.in_limit = b->in_pos + s->lzma2.compressed; - else - s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED; - - if (!lzma_main(s)) - return false; - - in_avail = s->rc.in_pos - b->in_pos; - if (in_avail > s->lzma2.compressed) - return false; - - s->lzma2.compressed -= in_avail; - b->in_pos = s->rc.in_pos; - } - - in_avail = b->in_size - b->in_pos; - if (in_avail < LZMA_IN_REQUIRED) - { - if (in_avail > s->lzma2.compressed) - in_avail = s->lzma2.compressed; - - memcpy(s->temp.buf, b->in + b->in_pos, in_avail); - s->temp.size = in_avail; - b->in_pos += in_avail; - } - - return true; -} - -/* - * Take care of the LZMA2 control layer, and forward the job of actual LZMA - * decoding or copying of uncompressed chunks to other functions. - */ -XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, struct xz_buf *b) -{ - uint32_t tmp; - - while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN) - { - switch (s->lzma2.sequence) - { - case SEQ_CONTROL: - /* - * LZMA2 control byte - * - * Exact values: - * 0x00 End marker - * 0x01 Dictionary reset followed by - * an uncompressed chunk - * 0x02 Uncompressed chunk (no dictionary reset) - * - * Highest three bits (s->control & 0xE0): - * 0xE0 Dictionary reset, new properties and state - * reset, followed by LZMA compressed chunk - * 0xC0 New properties and state reset, followed - * by LZMA compressed chunk (no dictionary - * reset) - * 0xA0 State reset using old properties, - * followed by LZMA compressed chunk (no - * dictionary reset) - * 0x80 LZMA chunk (no dictionary or state reset) - * - * For LZMA compressed chunks, the lowest five bits - * (s->control & 1F) are the highest bits of the - * uncompressed size (bits 16-20). - * - * A new LZMA2 stream must begin with a dictionary - * reset. The first LZMA chunk must set new - * properties and reset the LZMA state. - * - * Values that don't match anything described above - * are invalid and we return XZ_DATA_ERROR. - */ - tmp = b->in[b->in_pos++]; - - if (tmp == 0x00) - return XZ_STREAM_END; - - if (tmp >= 0xE0 || tmp == 0x01) - { - s->lzma2.need_props = true; - s->lzma2.need_dict_reset = false; - dict_reset(&s->dict, b); - } - else if (s->lzma2.need_dict_reset) - { - return XZ_DATA_ERROR; - } - - if (tmp >= 0x80) - { - s->lzma2.uncompressed = (tmp & 0x1F) << 16; - s->lzma2.sequence = SEQ_UNCOMPRESSED_1; - - if (tmp >= 0xC0) - { - /* - * When there are new properties, - * state reset is done at - * SEQ_PROPERTIES. - */ - s->lzma2.need_props = false; - s->lzma2.next_sequence = SEQ_PROPERTIES; - } - else if (s->lzma2.need_props) - { - return XZ_DATA_ERROR; - } - else - { - s->lzma2.next_sequence = SEQ_LZMA_PREPARE; - if (tmp >= 0xA0) - lzma_reset(s); - } - } - else - { - if (tmp > 0x02) - return XZ_DATA_ERROR; - - s->lzma2.sequence = SEQ_COMPRESSED_0; - s->lzma2.next_sequence = SEQ_COPY; - } - - break; - - case SEQ_UNCOMPRESSED_1: - s->lzma2.uncompressed += (uint32_t)b->in[b->in_pos++] << 8; - s->lzma2.sequence = SEQ_UNCOMPRESSED_2; - break; - - case SEQ_UNCOMPRESSED_2: - s->lzma2.uncompressed += (uint32_t)b->in[b->in_pos++] + 1; - s->lzma2.sequence = SEQ_COMPRESSED_0; - break; - - case SEQ_COMPRESSED_0: - s->lzma2.compressed = (uint32_t)b->in[b->in_pos++] << 8; - s->lzma2.sequence = SEQ_COMPRESSED_1; - break; - - case SEQ_COMPRESSED_1: - s->lzma2.compressed += (uint32_t)b->in[b->in_pos++] + 1; - s->lzma2.sequence = s->lzma2.next_sequence; - break; - - case SEQ_PROPERTIES: - if (!lzma_props(s, b->in[b->in_pos++])) - return XZ_DATA_ERROR; - - s->lzma2.sequence = SEQ_LZMA_PREPARE; - - case SEQ_LZMA_PREPARE: - if (s->lzma2.compressed < RC_INIT_BYTES) - return XZ_DATA_ERROR; - - if (!rc_read_init(&s->rc, b)) - return XZ_OK; - - s->lzma2.compressed -= RC_INIT_BYTES; - s->lzma2.sequence = SEQ_LZMA_RUN; - - case SEQ_LZMA_RUN: - /* - * Set dictionary limit to indicate how much we want - * to be encoded at maximum. Decode new data into the - * dictionary. Flush the new data from dictionary to - * b->out. Check if we finished decoding this chunk. - * In case the dictionary got full but we didn't fill - * the output buffer yet, we may run this loop - * multiple times without changing s->lzma2.sequence. - */ - dict_limit(&s->dict, - min_t(size_t, b->out_size - b->out_pos, s->lzma2.uncompressed)); - if (!lzma2_lzma(s, b)) - return XZ_DATA_ERROR; - - s->lzma2.uncompressed -= dict_flush(&s->dict, b); - - if (s->lzma2.uncompressed == 0) - { - if (s->lzma2.compressed > 0 || s->lzma.len > 0 || !rc_is_finished(&s->rc)) - return XZ_DATA_ERROR; - - rc_reset(&s->rc); - s->lzma2.sequence = SEQ_CONTROL; - } - else if (b->out_pos == b->out_size || - (b->in_pos == b->in_size && s->temp.size < s->lzma2.compressed)) - { - return XZ_OK; - } - - break; - - case SEQ_COPY: - dict_uncompressed(&s->dict, b, &s->lzma2.compressed); - if (s->lzma2.compressed > 0) - return XZ_OK; - - s->lzma2.sequence = SEQ_CONTROL; - break; - } - } - - return XZ_OK; -} - -XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, uint32_t dict_max) -{ - struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL); - if (s == NULL) - return NULL; - - s->dict.mode = mode; - s->dict.size_max = dict_max; - - if (DEC_IS_PREALLOC(mode)) - { - s->dict.buf = vmalloc(dict_max); - if (s->dict.buf == NULL) - { - kfree(s); - return NULL; - } - } - else if (DEC_IS_DYNALLOC(mode)) - { - s->dict.buf = NULL; - s->dict.allocated = 0; - } - - return s; -} - -XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props) -{ - /* This limits dictionary size to 3 GiB to keep parsing simpler. */ - if (props > 39) - return XZ_OPTIONS_ERROR; - - s->dict.size = 2 + (props & 1); - s->dict.size <<= (props >> 1) + 11; - - if (DEC_IS_MULTI(s->dict.mode)) - { - if (s->dict.size > s->dict.size_max) - return XZ_MEMLIMIT_ERROR; - - s->dict.end = s->dict.size; - - if (DEC_IS_DYNALLOC(s->dict.mode)) - { - if (s->dict.allocated < s->dict.size) - { - vfree(s->dict.buf); - s->dict.buf = vmalloc(s->dict.size); - if (s->dict.buf == NULL) - { - s->dict.allocated = 0; - return XZ_MEM_ERROR; - } - } - } - } - - s->lzma.len = 0; - - s->lzma2.sequence = SEQ_CONTROL; - s->lzma2.need_dict_reset = true; - - s->temp.size = 0; - - return XZ_OK; -} - -XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s) -{ - if (DEC_IS_MULTI(s->dict.mode)) - vfree(s->dict.buf); - - kfree(s); -} diff --git a/libraries/xz-embedded/src/xz_dec_stream.c b/libraries/xz-embedded/src/xz_dec_stream.c deleted file mode 100644 index f8d7be05..00000000 --- a/libraries/xz-embedded/src/xz_dec_stream.c +++ /dev/null @@ -1,860 +0,0 @@ -/* - * .xz Stream decoder - * - * Author: Lasse Collin - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -#include "xz_private.h" -#include "xz_stream.h" - -#ifdef XZ_USE_CRC64 -#define IS_CRC64(check_type) ((check_type) == XZ_CHECK_CRC64) -#else -#define IS_CRC64(check_type) false -#endif - -/* Hash used to validate the Index field */ -struct xz_dec_hash -{ - vli_type unpadded; - vli_type uncompressed; - uint32_t crc32; -}; - -struct xz_dec -{ - /* Position in dec_main() */ - enum - { - SEQ_STREAM_HEADER, - SEQ_BLOCK_START, - SEQ_BLOCK_HEADER, - SEQ_BLOCK_UNCOMPRESS, - SEQ_BLOCK_PADDING, - SEQ_BLOCK_CHECK, - SEQ_INDEX, - SEQ_INDEX_PADDING, - SEQ_INDEX_CRC32, - SEQ_STREAM_FOOTER - } sequence; - - /* Position in variable-length integers and Check fields */ - uint32_t pos; - - /* Variable-length integer decoded by dec_vli() */ - vli_type vli; - - /* Saved in_pos and out_pos */ - size_t in_start; - size_t out_start; - -#ifdef XZ_USE_CRC64 - /* CRC32 or CRC64 value in Block or CRC32 value in Index */ - uint64_t crc; -#else - /* CRC32 value in Block or Index */ - uint32_t crc; -#endif - - /* Type of the integrity check calculated from uncompressed data */ - enum xz_check check_type; - - /* Operation mode */ - enum xz_mode mode; - - /* - * True if the next call to xz_dec_run() is allowed to return - * XZ_BUF_ERROR. - */ - bool allow_buf_error; - - /* Information stored in Block Header */ - struct - { - /* - * Value stored in the Compressed Size field, or - * VLI_UNKNOWN if Compressed Size is not present. - */ - vli_type compressed; - - /* - * Value stored in the Uncompressed Size field, or - * VLI_UNKNOWN if Uncompressed Size is not present. - */ - vli_type uncompressed; - - /* Size of the Block Header field */ - uint32_t size; - } block_header; - - /* Information collected when decoding Blocks */ - struct - { - /* Observed compressed size of the current Block */ - vli_type compressed; - - /* Observed uncompressed size of the current Block */ - vli_type uncompressed; - - /* Number of Blocks decoded so far */ - vli_type count; - - /* - * Hash calculated from the Block sizes. This is used to - * validate the Index field. - */ - struct xz_dec_hash hash; - } block; - - /* Variables needed when verifying the Index field */ - struct - { - /* Position in dec_index() */ - enum - { - SEQ_INDEX_COUNT, - SEQ_INDEX_UNPADDED, - SEQ_INDEX_UNCOMPRESSED - } sequence; - - /* Size of the Index in bytes */ - vli_type size; - - /* Number of Records (matches block.count in valid files) */ - vli_type count; - - /* - * Hash calculated from the Records (matches block.hash in - * valid files). - */ - struct xz_dec_hash hash; - } index; - - /* - * Temporary buffer needed to hold Stream Header, Block Header, - * and Stream Footer. The Block Header is the biggest (1 KiB) - * so we reserve space according to that. buf[] has to be aligned - * to a multiple of four bytes; the size_t variables before it - * should guarantee this. - */ - struct - { - size_t pos; - size_t size; - uint8_t buf[1024]; - } temp; - - struct xz_dec_lzma2 *lzma2; - -#ifdef XZ_DEC_BCJ - struct xz_dec_bcj *bcj; - bool bcj_active; -#endif -}; - -#ifdef XZ_DEC_ANY_CHECK -/* Sizes of the Check field with different Check IDs */ -static const uint8_t check_sizes[16] = {0, 4, 4, 4, 8, 8, 8, 16, - 16, 16, 32, 32, 32, 64, 64, 64}; -#endif - -/* - * Fill s->temp by copying data starting from b->in[b->in_pos]. Caller - * must have set s->temp.pos to indicate how much data we are supposed - * to copy into s->temp.buf. Return true once s->temp.pos has reached - * s->temp.size. - */ -static bool fill_temp(struct xz_dec *s, struct xz_buf *b) -{ - size_t copy_size = min_t(size_t, b->in_size - b->in_pos, s->temp.size - s->temp.pos); - - memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size); - b->in_pos += copy_size; - s->temp.pos += copy_size; - - if (s->temp.pos == s->temp.size) - { - s->temp.pos = 0; - return true; - } - - return false; -} - -/* Decode a variable-length integer (little-endian base-128 encoding) */ -static enum xz_ret dec_vli(struct xz_dec *s, const uint8_t *in, size_t *in_pos, size_t in_size) -{ - uint8_t byte; - - if (s->pos == 0) - s->vli = 0; - - while (*in_pos < in_size) - { - byte = in[*in_pos]; - ++*in_pos; - - s->vli |= (vli_type)(byte & 0x7F) << s->pos; - - if ((byte & 0x80) == 0) - { - /* Don't allow non-minimal encodings. */ - if (byte == 0 && s->pos != 0) - return XZ_DATA_ERROR; - - s->pos = 0; - return XZ_STREAM_END; - } - - s->pos += 7; - if (s->pos == 7 * VLI_BYTES_MAX) - return XZ_DATA_ERROR; - } - - return XZ_OK; -} - -/* - * Decode the Compressed Data field from a Block. Update and validate - * the observed compressed and uncompressed sizes of the Block so that - * they don't exceed the values possibly stored in the Block Header - * (validation assumes that no integer overflow occurs, since vli_type - * is normally uint64_t). Update the CRC32 or CRC64 value if presence of - * the CRC32 or CRC64 field was indicated in Stream Header. - * - * Once the decoding is finished, validate that the observed sizes match - * the sizes possibly stored in the Block Header. Update the hash and - * Block count, which are later used to validate the Index field. - */ -static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) -{ - enum xz_ret ret; - - s->in_start = b->in_pos; - s->out_start = b->out_pos; - -#ifdef XZ_DEC_BCJ - if (s->bcj_active) - ret = xz_dec_bcj_run(s->bcj, s->lzma2, b); - else -#endif - ret = xz_dec_lzma2_run(s->lzma2, b); - - s->block.compressed += b->in_pos - s->in_start; - s->block.uncompressed += b->out_pos - s->out_start; - - /* - * There is no need to separately check for VLI_UNKNOWN, since - * the observed sizes are always smaller than VLI_UNKNOWN. - */ - if (s->block.compressed > s->block_header.compressed || - s->block.uncompressed > s->block_header.uncompressed) - return XZ_DATA_ERROR; - - if (s->check_type == XZ_CHECK_CRC32) - s->crc = xz_crc32(b->out + s->out_start, b->out_pos - s->out_start, s->crc); -#ifdef XZ_USE_CRC64 - else if (s->check_type == XZ_CHECK_CRC64) - s->crc = xz_crc64(b->out + s->out_start, b->out_pos - s->out_start, s->crc); -#endif - - if (ret == XZ_STREAM_END) - { - if (s->block_header.compressed != VLI_UNKNOWN && - s->block_header.compressed != s->block.compressed) - return XZ_DATA_ERROR; - - if (s->block_header.uncompressed != VLI_UNKNOWN && - s->block_header.uncompressed != s->block.uncompressed) - return XZ_DATA_ERROR; - - s->block.hash.unpadded += s->block_header.size + s->block.compressed; - -#ifdef XZ_DEC_ANY_CHECK - s->block.hash.unpadded += check_sizes[s->check_type]; -#else - if (s->check_type == XZ_CHECK_CRC32) - s->block.hash.unpadded += 4; - else if (IS_CRC64(s->check_type)) - s->block.hash.unpadded += 8; -#endif - - s->block.hash.uncompressed += s->block.uncompressed; - s->block.hash.crc32 = xz_crc32((const uint8_t *)&s->block.hash, sizeof(s->block.hash), - s->block.hash.crc32); - - ++s->block.count; - } - - return ret; -} - -/* Update the Index size and the CRC32 value. */ -static void index_update(struct xz_dec *s, const struct xz_buf *b) -{ - size_t in_used = b->in_pos - s->in_start; - s->index.size += in_used; - s->crc = xz_crc32(b->in + s->in_start, in_used, s->crc); -} - -/* - * Decode the Number of Records, Unpadded Size, and Uncompressed Size - * fields from the Index field. That is, Index Padding and CRC32 are not - * decoded by this function. - * - * This can return XZ_OK (more input needed), XZ_STREAM_END (everything - * successfully decoded), or XZ_DATA_ERROR (input is corrupt). - */ -static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) -{ - enum xz_ret ret; - - do - { - ret = dec_vli(s, b->in, &b->in_pos, b->in_size); - if (ret != XZ_STREAM_END) - { - index_update(s, b); - return ret; - } - - switch (s->index.sequence) - { - case SEQ_INDEX_COUNT: - s->index.count = s->vli; - - /* - * Validate that the Number of Records field - * indicates the same number of Records as - * there were Blocks in the Stream. - */ - if (s->index.count != s->block.count) - return XZ_DATA_ERROR; - - s->index.sequence = SEQ_INDEX_UNPADDED; - break; - - case SEQ_INDEX_UNPADDED: - s->index.hash.unpadded += s->vli; - s->index.sequence = SEQ_INDEX_UNCOMPRESSED; - break; - - case SEQ_INDEX_UNCOMPRESSED: - s->index.hash.uncompressed += s->vli; - s->index.hash.crc32 = xz_crc32((const uint8_t *)&s->index.hash, - sizeof(s->index.hash), s->index.hash.crc32); - --s->index.count; - s->index.sequence = SEQ_INDEX_UNPADDED; - break; - } - } while (s->index.count > 0); - - return XZ_STREAM_END; -} - -/* - * Validate that the next four or eight input bytes match the value - * of s->crc. s->pos must be zero when starting to validate the first byte. - * The "bits" argument allows using the same code for both CRC32 and CRC64. - */ -static enum xz_ret crc_validate(struct xz_dec *s, struct xz_buf *b, uint32_t bits) -{ - do - { - if (b->in_pos == b->in_size) - return XZ_OK; - - if (((s->crc >> s->pos) & 0xFF) != b->in[b->in_pos++]) - return XZ_DATA_ERROR; - - s->pos += 8; - - } while (s->pos < bits); - - s->crc = 0; - s->pos = 0; - - return XZ_STREAM_END; -} - -#ifdef XZ_DEC_ANY_CHECK -/* - * Skip over the Check field when the Check ID is not supported. - * Returns true once the whole Check field has been skipped over. - */ -static bool check_skip(struct xz_dec *s, struct xz_buf *b) -{ - while (s->pos < check_sizes[s->check_type]) - { - if (b->in_pos == b->in_size) - return false; - - ++b->in_pos; - ++s->pos; - } - - s->pos = 0; - - return true; -} -#endif - -/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */ -static enum xz_ret dec_stream_header(struct xz_dec *s) -{ - if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE)) - return XZ_FORMAT_ERROR; - - if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0) != - get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2)) - return XZ_DATA_ERROR; - - if (s->temp.buf[HEADER_MAGIC_SIZE] != 0) - return XZ_OPTIONS_ERROR; - - /* - * Of integrity checks, we support none (Check ID = 0), - * CRC32 (Check ID = 1), and optionally CRC64 (Check ID = 4). - * However, if XZ_DEC_ANY_CHECK is defined, we will accept other - * check types too, but then the check won't be verified and - * a warning (XZ_UNSUPPORTED_CHECK) will be given. - */ - s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1]; - -#ifdef XZ_DEC_ANY_CHECK - if (s->check_type > XZ_CHECK_MAX) - return XZ_OPTIONS_ERROR; - - if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type)) - return XZ_UNSUPPORTED_CHECK; -#else - if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type)) - return XZ_OPTIONS_ERROR; -#endif - - return XZ_OK; -} - -/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */ -static enum xz_ret dec_stream_footer(struct xz_dec *s) -{ - if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE)) - return XZ_DATA_ERROR; - - if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf)) - return XZ_DATA_ERROR; - - /* - * Validate Backward Size. Note that we never added the size of the - * Index CRC32 field to s->index.size, thus we use s->index.size / 4 - * instead of s->index.size / 4 - 1. - */ - if ((s->index.size >> 2) != get_le32(s->temp.buf + 4)) - return XZ_DATA_ERROR; - - if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type) - return XZ_DATA_ERROR; - - /* - * Use XZ_STREAM_END instead of XZ_OK to be more convenient - * for the caller. - */ - return XZ_STREAM_END; -} - -/* Decode the Block Header and initialize the filter chain. */ -static enum xz_ret dec_block_header(struct xz_dec *s) -{ - enum xz_ret ret; - - /* - * Validate the CRC32. We know that the temp buffer is at least - * eight bytes so this is safe. - */ - s->temp.size -= 4; - if (xz_crc32(s->temp.buf, s->temp.size, 0) != get_le32(s->temp.buf + s->temp.size)) - return XZ_DATA_ERROR; - - s->temp.pos = 2; - -/* - * Catch unsupported Block Flags. We support only one or two filters - * in the chain, so we catch that with the same test. - */ -#ifdef XZ_DEC_BCJ - if (s->temp.buf[1] & 0x3E) -#else - if (s->temp.buf[1] & 0x3F) -#endif - return XZ_OPTIONS_ERROR; - - /* Compressed Size */ - if (s->temp.buf[1] & 0x40) - { - if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) != XZ_STREAM_END) - return XZ_DATA_ERROR; - - s->block_header.compressed = s->vli; - } - else - { - s->block_header.compressed = VLI_UNKNOWN; - } - - /* Uncompressed Size */ - if (s->temp.buf[1] & 0x80) - { - if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) != XZ_STREAM_END) - return XZ_DATA_ERROR; - - s->block_header.uncompressed = s->vli; - } - else - { - s->block_header.uncompressed = VLI_UNKNOWN; - } - -#ifdef XZ_DEC_BCJ - /* If there are two filters, the first one must be a BCJ filter. */ - s->bcj_active = s->temp.buf[1] & 0x01; - if (s->bcj_active) - { - if (s->temp.size - s->temp.pos < 2) - return XZ_OPTIONS_ERROR; - - ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]); - if (ret != XZ_OK) - return ret; - - /* - * We don't support custom start offset, - * so Size of Properties must be zero. - */ - if (s->temp.buf[s->temp.pos++] != 0x00) - return XZ_OPTIONS_ERROR; - } -#endif - - /* Valid Filter Flags always take at least two bytes. */ - if (s->temp.size - s->temp.pos < 2) - return XZ_DATA_ERROR; - - /* Filter ID = LZMA2 */ - if (s->temp.buf[s->temp.pos++] != 0x21) - return XZ_OPTIONS_ERROR; - - /* Size of Properties = 1-byte Filter Properties */ - if (s->temp.buf[s->temp.pos++] != 0x01) - return XZ_OPTIONS_ERROR; - - /* Filter Properties contains LZMA2 dictionary size. */ - if (s->temp.size - s->temp.pos < 1) - return XZ_DATA_ERROR; - - ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]); - if (ret != XZ_OK) - return ret; - - /* The rest must be Header Padding. */ - while (s->temp.pos < s->temp.size) - if (s->temp.buf[s->temp.pos++] != 0x00) - return XZ_OPTIONS_ERROR; - - s->temp.pos = 0; - s->block.compressed = 0; - s->block.uncompressed = 0; - - return XZ_OK; -} - -static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) -{ - enum xz_ret ret; - - /* - * Store the start position for the case when we are in the middle - * of the Index field. - */ - s->in_start = b->in_pos; - - while (true) - { - switch (s->sequence) - { - case SEQ_STREAM_HEADER: - /* - * Stream Header is copied to s->temp, and then - * decoded from there. This way if the caller - * gives us only little input at a time, we can - * still keep the Stream Header decoding code - * simple. Similar approach is used in many places - * in this file. - */ - if (!fill_temp(s, b)) - return XZ_OK; - - /* - * If dec_stream_header() returns - * XZ_UNSUPPORTED_CHECK, it is still possible - * to continue decoding if working in multi-call - * mode. Thus, update s->sequence before calling - * dec_stream_header(). - */ - s->sequence = SEQ_BLOCK_START; - - ret = dec_stream_header(s); - if (ret != XZ_OK) - return ret; - - case SEQ_BLOCK_START: - /* We need one byte of input to continue. */ - if (b->in_pos == b->in_size) - return XZ_OK; - - /* See if this is the beginning of the Index field. */ - if (b->in[b->in_pos] == 0) - { - s->in_start = b->in_pos++; - s->sequence = SEQ_INDEX; - break; - } - - /* - * Calculate the size of the Block Header and - * prepare to decode it. - */ - s->block_header.size = ((uint32_t)b->in[b->in_pos] + 1) * 4; - - s->temp.size = s->block_header.size; - s->temp.pos = 0; - s->sequence = SEQ_BLOCK_HEADER; - - case SEQ_BLOCK_HEADER: - if (!fill_temp(s, b)) - return XZ_OK; - - ret = dec_block_header(s); - if (ret != XZ_OK) - return ret; - - s->sequence = SEQ_BLOCK_UNCOMPRESS; - - case SEQ_BLOCK_UNCOMPRESS: - ret = dec_block(s, b); - if (ret != XZ_STREAM_END) - return ret; - - s->sequence = SEQ_BLOCK_PADDING; - - case SEQ_BLOCK_PADDING: - /* - * Size of Compressed Data + Block Padding - * must be a multiple of four. We don't need - * s->block.compressed for anything else - * anymore, so we use it here to test the size - * of the Block Padding field. - */ - while (s->block.compressed & 3) - { - if (b->in_pos == b->in_size) - return XZ_OK; - - if (b->in[b->in_pos++] != 0) - return XZ_DATA_ERROR; - - ++s->block.compressed; - } - - s->sequence = SEQ_BLOCK_CHECK; - - case SEQ_BLOCK_CHECK: - if (s->check_type == XZ_CHECK_CRC32) - { - ret = crc_validate(s, b, 32); - if (ret != XZ_STREAM_END) - return ret; - } - else if (IS_CRC64(s->check_type)) - { - ret = crc_validate(s, b, 64); - if (ret != XZ_STREAM_END) - return ret; - } -#ifdef XZ_DEC_ANY_CHECK - else if (!check_skip(s, b)) - { - return XZ_OK; - } -#endif - - s->sequence = SEQ_BLOCK_START; - break; - - case SEQ_INDEX: - ret = dec_index(s, b); - if (ret != XZ_STREAM_END) - return ret; - - s->sequence = SEQ_INDEX_PADDING; - - case SEQ_INDEX_PADDING: - while ((s->index.size + (b->in_pos - s->in_start)) & 3) - { - if (b->in_pos == b->in_size) - { - index_update(s, b); - return XZ_OK; - } - - if (b->in[b->in_pos++] != 0) - return XZ_DATA_ERROR; - } - - /* Finish the CRC32 value and Index size. */ - index_update(s, b); - - /* Compare the hashes to validate the Index field. */ - if (!memeq(&s->block.hash, &s->index.hash, sizeof(s->block.hash))) - return XZ_DATA_ERROR; - - s->sequence = SEQ_INDEX_CRC32; - - case SEQ_INDEX_CRC32: - ret = crc_validate(s, b, 32); - if (ret != XZ_STREAM_END) - return ret; - - s->temp.size = STREAM_HEADER_SIZE; - s->sequence = SEQ_STREAM_FOOTER; - - case SEQ_STREAM_FOOTER: - if (!fill_temp(s, b)) - return XZ_OK; - - return dec_stream_footer(s); - } - } - - /* Never reached */ -} - -/* - * xz_dec_run() is a wrapper for dec_main() to handle some special cases in - * multi-call and single-call decoding. - * - * In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we - * are not going to make any progress anymore. This is to prevent the caller - * from calling us infinitely when the input file is truncated or otherwise - * corrupt. Since zlib-style API allows that the caller fills the input buffer - * only when the decoder doesn't produce any new output, we have to be careful - * to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only - * after the second consecutive call to xz_dec_run() that makes no progress. - * - * In single-call mode, if we couldn't decode everything and no error - * occurred, either the input is truncated or the output buffer is too small. - * Since we know that the last input byte never produces any output, we know - * that if all the input was consumed and decoding wasn't finished, the file - * must be corrupt. Otherwise the output buffer has to be too small or the - * file is corrupt in a way that decoding it produces too big output. - * - * If single-call decoding fails, we reset b->in_pos and b->out_pos back to - * their original values. This is because with some filter chains there won't - * be any valid uncompressed data in the output buffer unless the decoding - * actually succeeds (that's the price to pay of using the output buffer as - * the workspace). - */ -XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b) -{ - size_t in_start; - size_t out_start; - enum xz_ret ret; - - if (DEC_IS_SINGLE(s->mode)) - xz_dec_reset(s); - - in_start = b->in_pos; - out_start = b->out_pos; - ret = dec_main(s, b); - - if (DEC_IS_SINGLE(s->mode)) - { - if (ret == XZ_OK) - ret = b->in_pos == b->in_size ? XZ_DATA_ERROR : XZ_BUF_ERROR; - - if (ret != XZ_STREAM_END) - { - b->in_pos = in_start; - b->out_pos = out_start; - } - } - else if (ret == XZ_OK && in_start == b->in_pos && out_start == b->out_pos) - { - if (s->allow_buf_error) - ret = XZ_BUF_ERROR; - - s->allow_buf_error = true; - } - else - { - s->allow_buf_error = false; - } - - return ret; -} - -XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max) -{ - struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL); - if (s == NULL) - return NULL; - - s->mode = mode; - -#ifdef XZ_DEC_BCJ - s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode)); - if (s->bcj == NULL) - goto error_bcj; -#endif - - s->lzma2 = xz_dec_lzma2_create(mode, dict_max); - if (s->lzma2 == NULL) - goto error_lzma2; - - xz_dec_reset(s); - return s; - -error_lzma2: -#ifdef XZ_DEC_BCJ - xz_dec_bcj_end(s->bcj); -error_bcj: -#endif - kfree(s); - return NULL; -} - -XZ_EXTERN void xz_dec_reset(struct xz_dec *s) -{ - s->sequence = SEQ_STREAM_HEADER; - s->allow_buf_error = false; - s->pos = 0; - s->crc = 0; - memzero(&s->block, sizeof(s->block)); - memzero(&s->index, sizeof(s->index)); - s->temp.pos = 0; - s->temp.size = STREAM_HEADER_SIZE; -} - -XZ_EXTERN void xz_dec_end(struct xz_dec *s) -{ - if (s != NULL) - { - xz_dec_lzma2_end(s->lzma2); -#ifdef XZ_DEC_BCJ - xz_dec_bcj_end(s->bcj); -#endif - kfree(s); - } -} diff --git a/libraries/xz-embedded/src/xz_lzma2.h b/libraries/xz-embedded/src/xz_lzma2.h deleted file mode 100644 index 82a425f2..00000000 --- a/libraries/xz-embedded/src/xz_lzma2.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * LZMA2 definitions - * - * Authors: Lasse Collin - * Igor Pavlov - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -#ifndef XZ_LZMA2_H -#define XZ_LZMA2_H - -/* Range coder constants */ -#define RC_SHIFT_BITS 8 -#define RC_TOP_BITS 24 -#define RC_TOP_VALUE (1 << RC_TOP_BITS) -#define RC_BIT_MODEL_TOTAL_BITS 11 -#define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS) -#define RC_MOVE_BITS 5 - -/* - * Maximum number of position states. A position state is the lowest pb - * number of bits of the current uncompressed offset. In some places there - * are different sets of probabilities for different position states. - */ -#define POS_STATES_MAX (1 << 4) - -/* - * This enum is used to track which LZMA symbols have occurred most recently - * and in which order. This information is used to predict the next symbol. - * - * Symbols: - * - Literal: One 8-bit byte - * - Match: Repeat a chunk of data at some distance - * - Long repeat: Multi-byte match at a recently seen distance - * - Short repeat: One-byte repeat at a recently seen distance - * - * The symbol names are in from STATE_oldest_older_previous. REP means - * either short or long repeated match, and NONLIT means any non-literal. - */ -enum lzma_state -{ - STATE_LIT_LIT, - STATE_MATCH_LIT_LIT, - STATE_REP_LIT_LIT, - STATE_SHORTREP_LIT_LIT, - STATE_MATCH_LIT, - STATE_REP_LIT, - STATE_SHORTREP_LIT, - STATE_LIT_MATCH, - STATE_LIT_LONGREP, - STATE_LIT_SHORTREP, - STATE_NONLIT_MATCH, - STATE_NONLIT_REP -}; - -/* Total number of states */ -#define STATES 12 - -/* The lowest 7 states indicate that the previous state was a literal. */ -#define LIT_STATES 7 - -/* Indicate that the latest symbol was a literal. */ -static inline void lzma_state_literal(enum lzma_state *state) -{ - if (*state <= STATE_SHORTREP_LIT_LIT) - *state = STATE_LIT_LIT; - else if (*state <= STATE_LIT_SHORTREP) - *state -= 3; - else - *state -= 6; -} - -/* Indicate that the latest symbol was a match. */ -static inline void lzma_state_match(enum lzma_state *state) -{ - *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH; -} - -/* Indicate that the latest state was a long repeated match. */ -static inline void lzma_state_long_rep(enum lzma_state *state) -{ - *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP; -} - -/* Indicate that the latest symbol was a short match. */ -static inline void lzma_state_short_rep(enum lzma_state *state) -{ - *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP; -} - -/* Test if the previous symbol was a literal. */ -static inline bool lzma_state_is_literal(enum lzma_state state) -{ - return state < LIT_STATES; -} - -/* Each literal coder is divided in three sections: - * - 0x001-0x0FF: Without match byte - * - 0x101-0x1FF: With match byte; match bit is 0 - * - 0x201-0x2FF: With match byte; match bit is 1 - * - * Match byte is used when the previous LZMA symbol was something else than - * a literal (that is, it was some kind of match). - */ -#define LITERAL_CODER_SIZE 0x300 - -/* Maximum number of literal coders */ -#define LITERAL_CODERS_MAX (1 << 4) - -/* Minimum length of a match is two bytes. */ -#define MATCH_LEN_MIN 2 - -/* Match length is encoded with 4, 5, or 10 bits. - * - * Length Bits - * 2-9 4 = Choice=0 + 3 bits - * 10-17 5 = Choice=1 + Choice2=0 + 3 bits - * 18-273 10 = Choice=1 + Choice2=1 + 8 bits - */ -#define LEN_LOW_BITS 3 -#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS) -#define LEN_MID_BITS 3 -#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS) -#define LEN_HIGH_BITS 8 -#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS) -#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS) - -/* - * Maximum length of a match is 273 which is a result of the encoding - * described above. - */ -#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1) - -/* - * Different sets of probabilities are used for match distances that have - * very short match length: Lengths of 2, 3, and 4 bytes have a separate - * set of probabilities for each length. The matches with longer length - * use a shared set of probabilities. - */ -#define DIST_STATES 4 - -/* - * Get the index of the appropriate probability array for decoding - * the distance slot. - */ -static inline uint32_t lzma_get_dist_state(uint32_t len) -{ - return len < DIST_STATES + MATCH_LEN_MIN ? len - MATCH_LEN_MIN : DIST_STATES - 1; -} - -/* - * The highest two bits of a 32-bit match distance are encoded using six bits. - * This six-bit value is called a distance slot. This way encoding a 32-bit - * value takes 6-36 bits, larger values taking more bits. - */ -#define DIST_SLOT_BITS 6 -#define DIST_SLOTS (1 << DIST_SLOT_BITS) - -/* Match distances up to 127 are fully encoded using probabilities. Since - * the highest two bits (distance slot) are always encoded using six bits, - * the distances 0-3 don't need any additional bits to encode, since the - * distance slot itself is the same as the actual distance. DIST_MODEL_START - * indicates the first distance slot where at least one additional bit is - * needed. - */ -#define DIST_MODEL_START 4 - -/* - * Match distances greater than 127 are encoded in three pieces: - * - distance slot: the highest two bits - * - direct bits: 2-26 bits below the highest two bits - * - alignment bits: four lowest bits - * - * Direct bits don't use any probabilities. - * - * The distance slot value of 14 is for distances 128-191. - */ -#define DIST_MODEL_END 14 - -/* Distance slots that indicate a distance <= 127. */ -#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2) -#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS) - -/* - * For match distances greater than 127, only the highest two bits and the - * lowest four bits (alignment) is encoded using probabilities. - */ -#define ALIGN_BITS 4 -#define ALIGN_SIZE (1 << ALIGN_BITS) -#define ALIGN_MASK (ALIGN_SIZE - 1) - -/* Total number of all probability variables */ -#define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX *LITERAL_CODER_SIZE) - -/* - * LZMA remembers the four most recent match distances. Reusing these - * distances tends to take less space than re-encoding the actual - * distance value. - */ -#define REPS 4 - -#endif diff --git a/libraries/xz-embedded/src/xz_private.h b/libraries/xz-embedded/src/xz_private.h deleted file mode 100644 index 1b616430..00000000 --- a/libraries/xz-embedded/src/xz_private.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Private includes and definitions - * - * Author: Lasse Collin - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -#ifndef XZ_PRIVATE_H -#define XZ_PRIVATE_H - -#ifdef __KERNEL__ -#include -#include -#include -/* XZ_PREBOOT may be defined only via decompress_unxz.c. */ -#ifndef XZ_PREBOOT -#include -#include -#include -#ifdef CONFIG_XZ_DEC_X86 -#define XZ_DEC_X86 -#endif -#ifdef CONFIG_XZ_DEC_POWERPC -#define XZ_DEC_POWERPC -#endif -#ifdef CONFIG_XZ_DEC_IA64 -#define XZ_DEC_IA64 -#endif -#ifdef CONFIG_XZ_DEC_ARM -#define XZ_DEC_ARM -#endif -#ifdef CONFIG_XZ_DEC_ARMTHUMB -#define XZ_DEC_ARMTHUMB -#endif -#ifdef CONFIG_XZ_DEC_SPARC -#define XZ_DEC_SPARC -#endif -#define memeq(a, b, size) (memcmp(a, b, size) == 0) -#define memzero(buf, size) memset(buf, 0, size) -#endif -#define get_le32(p) le32_to_cpup((const uint32_t *)(p)) -#else -/* - * For userspace builds, use a separate header to define the required - * macros and functions. This makes it easier to adapt the code into - * different environments and avoids clutter in the Linux kernel tree. - */ -#include "xz_config.h" -#endif - -/* If no specific decoding mode is requested, enable support for all modes. */ -#if !defined(XZ_DEC_SINGLE) && !defined(XZ_DEC_PREALLOC) && !defined(XZ_DEC_DYNALLOC) -#define XZ_DEC_SINGLE -#define XZ_DEC_PREALLOC -#define XZ_DEC_DYNALLOC -#endif - -/* - * The DEC_IS_foo(mode) macros are used in "if" statements. If only some - * of the supported modes are enabled, these macros will evaluate to true or - * false at compile time and thus allow the compiler to omit unneeded code. - */ -#ifdef XZ_DEC_SINGLE -#define DEC_IS_SINGLE(mode) ((mode) == XZ_SINGLE) -#else -#define DEC_IS_SINGLE(mode) (false) -#endif - -#ifdef XZ_DEC_PREALLOC -#define DEC_IS_PREALLOC(mode) ((mode) == XZ_PREALLOC) -#else -#define DEC_IS_PREALLOC(mode) (false) -#endif - -#ifdef XZ_DEC_DYNALLOC -#define DEC_IS_DYNALLOC(mode) ((mode) == XZ_DYNALLOC) -#else -#define DEC_IS_DYNALLOC(mode) (false) -#endif - -#if !defined(XZ_DEC_SINGLE) -#define DEC_IS_MULTI(mode) (true) -#elif defined(XZ_DEC_PREALLOC) || defined(XZ_DEC_DYNALLOC) -#define DEC_IS_MULTI(mode) ((mode) != XZ_SINGLE) -#else -#define DEC_IS_MULTI(mode) (false) -#endif - -/* - * If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ. - * XZ_DEC_BCJ is used to enable generic support for BCJ decoders. - */ -#ifndef XZ_DEC_BCJ -#if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) || defined(XZ_DEC_IA64) || \ - defined(XZ_DEC_ARM) || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) || \ - defined(XZ_DEC_SPARC) -#define XZ_DEC_BCJ -#endif -#endif - -/* - * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used - * before calling xz_dec_lzma2_run(). - */ -XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, uint32_t dict_max); - -/* - * Decode the LZMA2 properties (one byte) and reset the decoder. Return - * XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not - * big enough, and XZ_OPTIONS_ERROR if props indicates something that this - * decoder doesn't support. - */ -XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props); - -/* Decode raw LZMA2 stream from b->in to b->out. */ -XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, struct xz_buf *b); - -/* Free the memory allocated for the LZMA2 decoder. */ -XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s); - -#ifdef XZ_DEC_BCJ -/* - * Allocate memory for BCJ decoders. xz_dec_bcj_reset() must be used before - * calling xz_dec_bcj_run(). - */ -XZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call); - -/* - * Decode the Filter ID of a BCJ filter. This implementation doesn't - * support custom start offsets, so no decoding of Filter Properties - * is needed. Returns XZ_OK if the given Filter ID is supported. - * Otherwise XZ_OPTIONS_ERROR is returned. - */ -XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id); - -/* - * Decode raw BCJ + LZMA2 stream. This must be used only if there actually is - * a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run() - * must be called directly. - */ -XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, struct xz_dec_lzma2 *lzma2, - struct xz_buf *b); - -/* Free the memory allocated for the BCJ filters. */ -#define xz_dec_bcj_end(s) kfree(s) -#endif - -#endif diff --git a/libraries/xz-embedded/src/xz_stream.h b/libraries/xz-embedded/src/xz_stream.h deleted file mode 100644 index b3d2c9fd..00000000 --- a/libraries/xz-embedded/src/xz_stream.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Definitions for handling the .xz file format - * - * Author: Lasse Collin - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -#ifndef XZ_STREAM_H -#define XZ_STREAM_H - -#if defined(__KERNEL__) && !XZ_INTERNAL_CRC32 -#include -#undef crc32 -#define xz_crc32(buf, size, crc) (~crc32_le(~(uint32_t)(crc), buf, size)) -#endif - -/* - * See the .xz file format specification at - * http://tukaani.org/xz/xz-file-format.txt - * to understand the container format. - */ - -#define STREAM_HEADER_SIZE 12 - -#define HEADER_MAGIC "\3757zXZ" -#define HEADER_MAGIC_SIZE 6 - -#define FOOTER_MAGIC "YZ" -#define FOOTER_MAGIC_SIZE 2 - -/* - * Variable-length integer can hold a 63-bit unsigned integer or a special - * value indicating that the value is unknown. - * - * Experimental: vli_type can be defined to uint32_t to save a few bytes - * in code size (no effect on speed). Doing so limits the uncompressed and - * compressed size of the file to less than 256 MiB and may also weaken - * error detection slightly. - */ -typedef uint64_t vli_type; - -#define VLI_MAX ((vli_type) - 1 / 2) -#define VLI_UNKNOWN ((vli_type) - 1) - -/* Maximum encoded size of a VLI */ -#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7) - -/* Integrity Check types */ -enum xz_check -{ - XZ_CHECK_NONE = 0, - XZ_CHECK_CRC32 = 1, - XZ_CHECK_CRC64 = 4, - XZ_CHECK_SHA256 = 10 -}; - -/* Maximum possible Check ID */ -#define XZ_CHECK_MAX 15 - -#endif diff --git a/libraries/xz-embedded/xzminidec.c b/libraries/xz-embedded/xzminidec.c deleted file mode 100644 index 44f60602..00000000 --- a/libraries/xz-embedded/xzminidec.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Simple XZ decoder command line tool - * - * Author: Lasse Collin - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -/* - * This is really limited: Not all filters from .xz format are supported, - * only CRC32 is supported as the integrity check, and decoding of - * concatenated .xz streams is not supported. Thus, you may want to look - * at xzdec from XZ Utils if a few KiB bigger tool is not a problem. - */ - -#include -#include -#include -#include "xz.h" - -static uint8_t in[BUFSIZ]; -static uint8_t out[BUFSIZ]; - -int main(int argc, char **argv) -{ - struct xz_buf b; - struct xz_dec *s; - enum xz_ret ret; - const char *msg; - - if (argc >= 2 && strcmp(argv[1], "--help") == 0) - { - fputs("Uncompress a .xz file from stdin to stdout.\n" - "Arguments other than `--help' are ignored.\n", - stdout); - return 0; - } - - xz_crc32_init(); -#ifdef XZ_USE_CRC64 - xz_crc64_init(); -#endif - - /* - * Support up to 64 MiB dictionary. The actually needed memory - * is allocated once the headers have been parsed. - */ - s = xz_dec_init(XZ_DYNALLOC, 1 << 26); - if (s == NULL) - { - msg = "Memory allocation failed\n"; - goto error; - } - - b.in = in; - b.in_pos = 0; - b.in_size = 0; - b.out = out; - b.out_pos = 0; - b.out_size = BUFSIZ; - - while (true) - { - if (b.in_pos == b.in_size) - { - b.in_size = fread(in, 1, sizeof(in), stdin); - b.in_pos = 0; - } - - ret = xz_dec_run(s, &b); - - if (b.out_pos == sizeof(out)) - { - if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) - { - msg = "Write error\n"; - goto error; - } - - b.out_pos = 0; - } - - if (ret == XZ_OK) - continue; - -#ifdef XZ_DEC_ANY_CHECK - if (ret == XZ_UNSUPPORTED_CHECK) - { - fputs(argv[0], stderr); - fputs(": ", stderr); - fputs("Unsupported check; not verifying " - "file integrity\n", - stderr); - continue; - } -#endif - - if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos || fclose(stdout)) - { - msg = "Write error\n"; - goto error; - } - - switch (ret) - { - case XZ_STREAM_END: - xz_dec_end(s); - return 0; - - case XZ_MEM_ERROR: - msg = "Memory allocation failed\n"; - goto error; - - case XZ_MEMLIMIT_ERROR: - msg = "Memory usage limit reached\n"; - goto error; - - case XZ_FORMAT_ERROR: - msg = "Not a .xz file\n"; - goto error; - - case XZ_OPTIONS_ERROR: - msg = "Unsupported options in the .xz headers\n"; - goto error; - - case XZ_DATA_ERROR: - case XZ_BUF_ERROR: - msg = "File is corrupt\n"; - goto error; - - default: - msg = "Bug!\n"; - goto error; - } - } - -error: - xz_dec_end(s); - fputs(argv[0], stderr); - fputs(": ", stderr); - fputs(msg, stderr); - return 1; -}